You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

download.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package repo
  6. import (
  7. "fmt"
  8. "io"
  9. "path"
  10. "strings"
  11. "code.gitea.io/git"
  12. "code.gitea.io/gitea/modules/base"
  13. "code.gitea.io/gitea/modules/context"
  14. "code.gitea.io/gitea/modules/lfs"
  15. )
  16. // ServeData download file from io.Reader
  17. func ServeData(ctx *context.Context, name string, reader io.Reader) error {
  18. buf := make([]byte, 1024)
  19. n, _ := reader.Read(buf)
  20. if n >= 0 {
  21. buf = buf[:n]
  22. }
  23. ctx.Resp.Header().Set("Cache-Control", "public,max-age=86400")
  24. name = path.Base(name)
  25. // Google Chrome dislike commas in filenames, so let's change it to a space
  26. name = strings.Replace(name, ",", " ", -1)
  27. if base.IsTextFile(buf) || ctx.QueryBool("render") {
  28. ctx.Resp.Header().Set("Content-Type", "text/plain; charset=utf-8")
  29. } else if base.IsImageFile(buf) || base.IsPDFFile(buf) {
  30. ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, name))
  31. } else {
  32. ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name))
  33. }
  34. ctx.Resp.Write(buf)
  35. _, err := io.Copy(ctx.Resp, reader)
  36. return err
  37. }
  38. // ServeBlob download a git.Blob
  39. func ServeBlob(ctx *context.Context, blob *git.Blob) error {
  40. dataRc, err := blob.DataAsync()
  41. if err != nil {
  42. return err
  43. }
  44. defer dataRc.Close()
  45. return ServeData(ctx, ctx.Repo.TreePath, dataRc)
  46. }
  47. // ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
  48. func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
  49. dataRc, err := blob.DataAsync()
  50. if err != nil {
  51. return err
  52. }
  53. defer dataRc.Close()
  54. if meta, _ := lfs.ReadPointerFile(dataRc); meta != nil {
  55. meta, _ = ctx.Repo.Repository.GetLFSMetaObjectByOid(meta.Oid)
  56. if meta == nil {
  57. return ServeBlob(ctx, blob)
  58. }
  59. lfsDataRc, err := lfs.ReadMetaObject(meta)
  60. if err != nil {
  61. return err
  62. }
  63. return ServeData(ctx, ctx.Repo.TreePath, lfsDataRc)
  64. }
  65. return ServeBlob(ctx, blob)
  66. }
  67. // SingleDownload download a file by repos path
  68. func SingleDownload(ctx *context.Context) {
  69. blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreePath)
  70. if err != nil {
  71. if git.IsErrNotExist(err) {
  72. ctx.NotFound("GetBlobByPath", nil)
  73. } else {
  74. ctx.ServerError("GetBlobByPath", err)
  75. }
  76. return
  77. }
  78. if err = ServeBlob(ctx, blob); err != nil {
  79. ctx.ServerError("ServeBlob", err)
  80. }
  81. }
  82. // SingleDownloadOrLFS download a file by repos path redirecting to LFS if necessary
  83. func SingleDownloadOrLFS(ctx *context.Context) {
  84. blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreePath)
  85. if err != nil {
  86. if git.IsErrNotExist(err) {
  87. ctx.NotFound("GetBlobByPath", nil)
  88. } else {
  89. ctx.ServerError("GetBlobByPath", err)
  90. }
  91. return
  92. }
  93. if err = ServeBlobOrLFS(ctx, blob); err != nil {
  94. ctx.ServerError("ServeBlobOrLFS", err)
  95. }
  96. }
  97. // DownloadByID download a file by sha1 ID
  98. func DownloadByID(ctx *context.Context) {
  99. blob, err := ctx.Repo.GitRepo.GetBlob(ctx.Params("sha"))
  100. if err != nil {
  101. if git.IsErrNotExist(err) {
  102. ctx.NotFound("GetBlob", nil)
  103. } else {
  104. ctx.ServerError("GetBlob", err)
  105. }
  106. return
  107. }
  108. if err = ServeBlob(ctx, blob); err != nil {
  109. ctx.ServerError("ServeBlob", err)
  110. }
  111. }
  112. // DownloadByIDOrLFS download a file by sha1 ID taking account of LFS
  113. func DownloadByIDOrLFS(ctx *context.Context) {
  114. blob, err := ctx.Repo.GitRepo.GetBlob(ctx.Params("sha"))
  115. if err != nil {
  116. if git.IsErrNotExist(err) {
  117. ctx.NotFound("GetBlob", nil)
  118. } else {
  119. ctx.ServerError("GetBlob", err)
  120. }
  121. return
  122. }
  123. if err = ServeBlobOrLFS(ctx, blob); err != nil {
  124. ctx.ServerError("ServeBlob", err)
  125. }
  126. }