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.

106 lines
2.5 KiB

  1. package operation
  2. import (
  3. "code.google.com/p/weed-fs/go/glog"
  4. "io"
  5. "mime"
  6. "os"
  7. "path"
  8. "strconv"
  9. "strings"
  10. )
  11. type FilePart struct {
  12. Reader io.Reader //required, all rest are optional
  13. FileName string
  14. IsGzipped bool
  15. MimeType string
  16. ModTime int64 //in seconds
  17. }
  18. type SubmitResult struct {
  19. FileName string `json:"fileName"`
  20. FileUrl string `json:"fileUrl"`
  21. Fid string `json:"fid"`
  22. Size int `json:"size"`
  23. Error string `json:"error"`
  24. }
  25. func SubmitFiles(master string, files []FilePart, replication string) ([]SubmitResult, error) {
  26. results := make([]SubmitResult, len(files))
  27. for index, file := range files {
  28. results[index].FileName = file.FileName
  29. }
  30. ret, err := Assign(master, len(files), replication)
  31. if err != nil {
  32. for index, _ := range files {
  33. results[index].Error = err.Error()
  34. }
  35. return results, err
  36. }
  37. for index, file := range files {
  38. fid := ret.Fid
  39. if index > 0 {
  40. fid = fid + "_" + strconv.Itoa(index)
  41. }
  42. results[index].Size, err = file.Upload(ret.PublicUrl, fid)
  43. if err != nil {
  44. fid = ""
  45. results[index].Error = err.Error()
  46. }
  47. results[index].Fid = fid
  48. results[index].FileUrl = ret.PublicUrl + "/" + fid
  49. }
  50. return results, nil
  51. }
  52. func NewFileParts(fullPathFilenames []string) (ret []FilePart, err error) {
  53. ret = make([]FilePart, len(fullPathFilenames))
  54. for index, file := range fullPathFilenames {
  55. if ret[index], err = NewFilePart(file); err != nil {
  56. return
  57. }
  58. }
  59. return
  60. }
  61. func NewFilePart(fullPathFilename string) (ret FilePart, err error) {
  62. fh, openErr := os.Open(fullPathFilename)
  63. if openErr != nil {
  64. glog.V(0).Info("Failed to open file: ", fullPathFilename)
  65. return ret, openErr
  66. }
  67. ret.Reader = fh
  68. if fi, fiErr := fh.Stat(); fiErr != nil {
  69. glog.V(0).Info("Failed to stat file:", fullPathFilename)
  70. return ret, fiErr
  71. } else {
  72. ret.ModTime = fi.ModTime().UTC().Unix()
  73. }
  74. ext := strings.ToLower(path.Ext(fullPathFilename))
  75. ret.IsGzipped = ext == ".gz"
  76. if ret.IsGzipped {
  77. ret.FileName = fullPathFilename[0 : len(fullPathFilename)-3]
  78. }
  79. ret.FileName = fullPathFilename
  80. if ext != "" {
  81. ret.MimeType = mime.TypeByExtension(ext)
  82. }
  83. return ret, nil
  84. }
  85. func (fi FilePart) Upload(server string, fid string) (int, error) {
  86. fileUrl := "http://" + server + "/" + fid
  87. if fi.ModTime != 0 {
  88. fileUrl += "?ts=" + strconv.Itoa(int(fi.ModTime))
  89. }
  90. if closer, ok := fi.Reader.(io.Closer); ok {
  91. defer closer.Close()
  92. }
  93. ret, e := Upload(fileUrl, fi.FileName, fi.Reader, fi.IsGzipped, fi.MimeType)
  94. if e != nil {
  95. return 0, e
  96. }
  97. return ret.Size, e
  98. }