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.

129 lines
2.8 KiB

  1. package weed_server
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strings"
  6. "github.com/chrislusf/seaweedfs/weed/glog"
  7. "github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
  8. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  9. "github.com/chrislusf/seaweedfs/weed/util"
  10. )
  11. func (vs *VolumeServer) FileGet(req *volume_server_pb.FileGetRequest, stream volume_server_pb.VolumeServer_FileGetServer) error {
  12. headResponse := &volume_server_pb.FileGetResponse{}
  13. n := new(needle.Needle)
  14. commaIndex := strings.LastIndex(req.FileId, ",")
  15. vid := req.FileId[:commaIndex]
  16. fid := req.FileId[commaIndex+1:]
  17. volumeId, err := needle.NewVolumeId(vid)
  18. if err != nil {
  19. headResponse.ErrorCode = http.StatusBadRequest
  20. return stream.Send(headResponse)
  21. }
  22. err = n.ParsePath(fid)
  23. if err != nil {
  24. headResponse.ErrorCode = http.StatusBadRequest
  25. return stream.Send(headResponse)
  26. }
  27. hasVolume := vs.store.HasVolume(volumeId)
  28. _, hasEcVolume := vs.store.FindEcVolume(volumeId)
  29. if !hasVolume && !hasEcVolume {
  30. headResponse.ErrorCode = http.StatusMovedPermanently
  31. return stream.Send(headResponse)
  32. }
  33. cookie := n.Cookie
  34. var count int
  35. if hasVolume {
  36. count, err = vs.store.ReadVolumeNeedle(volumeId, n)
  37. } else if hasEcVolume {
  38. count, err = vs.store.ReadEcShardNeedle(volumeId, n)
  39. }
  40. if err != nil || count < 0 {
  41. headResponse.ErrorCode = http.StatusNotFound
  42. return stream.Send(headResponse)
  43. }
  44. if n.Cookie != cookie {
  45. headResponse.ErrorCode = http.StatusNotFound
  46. return stream.Send(headResponse)
  47. }
  48. if n.LastModified != 0 {
  49. headResponse.LastModified = n.LastModified
  50. }
  51. headResponse.Etag = n.Etag()
  52. if n.HasPairs() {
  53. pairMap := make(map[string]string)
  54. err = json.Unmarshal(n.Pairs, &pairMap)
  55. if err != nil {
  56. glog.V(0).Infoln("Unmarshal pairs error:", err)
  57. }
  58. headResponse.Headers = pairMap
  59. }
  60. /*
  61. // skip this, no redirection
  62. if vs.tryHandleChunkedFile(n, filename, w, r) {
  63. return
  64. }
  65. */
  66. if n.NameSize > 0 {
  67. headResponse.Filename = string(n.Name)
  68. }
  69. mtype := ""
  70. if n.MimeSize > 0 {
  71. mt := string(n.Mime)
  72. if !strings.HasPrefix(mt, "application/octet-stream") {
  73. mtype = mt
  74. }
  75. }
  76. headResponse.ContentType = mtype
  77. headResponse.IsGzipped = n.IsGzipped()
  78. if n.IsGzipped() && req.AcceptGzip {
  79. if n.Data, err = util.UnGzipData(n.Data); err != nil {
  80. glog.V(0).Infof("ungzip %s error: %v", req.FileId, err)
  81. }
  82. }
  83. headResponse.ContentLength = uint32(len(n.Data))
  84. bytesToRead := len(n.Data)
  85. bytesRead := 0
  86. t := headResponse
  87. for bytesRead < bytesToRead {
  88. stopIndex := bytesRead + BufferSizeLimit
  89. if stopIndex > bytesToRead {
  90. stopIndex = bytesToRead
  91. }
  92. if t == nil {
  93. t = &volume_server_pb.FileGetResponse{}
  94. }
  95. t.Data = n.Data[bytesRead:stopIndex]
  96. err = stream.Send(t)
  97. t = nil
  98. if err != nil {
  99. return err
  100. }
  101. bytesRead = stopIndex
  102. }
  103. return nil
  104. }