FileStoreHandler.coffee 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. logger = require("logger-sharelatex")
  2. fs = require("fs")
  3. request = require("request")
  4. settings = require("settings-sharelatex")
  5. oneMinInMs = 60 * 1000
  6. fiveMinsInMs = oneMinInMs * 5
  7. module.exports = FileStoreHandler =
  8. uploadFileFromDisk: (project_id, file_id, fsPath, callback)->
  9. fs.lstat fsPath, (err, stat)->
  10. if err?
  11. logger.err err:err, project_id:project_id, file_id:file_id, fsPath:fsPath, "error stating file"
  12. callback(err)
  13. if !stat?
  14. logger.err project_id:project_id, file_id:file_id, fsPath:fsPath, "stat is not available, can not check file from disk"
  15. return callback(new Error("error getting stat, not available"))
  16. if !stat.isFile()
  17. logger.log project_id:project_id, file_id:file_id, fsPath:fsPath, "tried to upload symlink, not contining"
  18. return callback(new Error("can not upload symlink"))
  19. _cb = callback
  20. callback = (err, url) ->
  21. callback = -> # avoid double callbacks
  22. _cb(err, url)
  23. logger.log project_id:project_id, file_id:file_id, fsPath:fsPath, "uploading file from disk"
  24. readStream = fs.createReadStream(fsPath)
  25. readStream.on "error", (err)->
  26. logger.err err:err, project_id:project_id, file_id:file_id, fsPath:fsPath, "something went wrong on the read stream of uploadFileFromDisk"
  27. callback err
  28. readStream.on "open", () ->
  29. url = FileStoreHandler._buildUrl(project_id, file_id)
  30. opts =
  31. method: "post"
  32. uri: url
  33. timeout:fiveMinsInMs
  34. writeStream = request(opts)
  35. writeStream.on "error", (err)->
  36. logger.err err:err, project_id:project_id, file_id:file_id, fsPath:fsPath, "something went wrong on the write stream of uploadFileFromDisk"
  37. callback err
  38. writeStream.on 'response', (response) ->
  39. if response.statusCode not in [200, 201]
  40. err = new Error("non-ok response from filestore for upload: #{response.statusCode}")
  41. logger.err {err, statusCode: response.statusCode}, "error uploading to filestore"
  42. callback(err)
  43. else
  44. callback(null, url)
  45. readStream.pipe writeStream
  46. getFileStream: (project_id, file_id, query, callback)->
  47. logger.log project_id:project_id, file_id:file_id, query:query, "getting file stream from file store"
  48. queryString = ""
  49. if query? and query["format"]?
  50. queryString = "?format=#{query['format']}"
  51. opts =
  52. method : "get"
  53. uri: "#{@_buildUrl(project_id, file_id)}#{queryString}"
  54. timeout:fiveMinsInMs
  55. headers: {}
  56. if query? and query['range']?
  57. rangeText = query['range']
  58. if rangeText && rangeText.match? && rangeText.match(/\d+-\d+/)
  59. opts.headers['range'] = "bytes=#{query['range']}"
  60. readStream = request(opts)
  61. readStream.on "error", (err) ->
  62. logger.err {err, project_id, file_id, query}, "error in file stream"
  63. callback(null, readStream)
  64. deleteFile: (project_id, file_id, callback)->
  65. logger.log project_id:project_id, file_id:file_id, "telling file store to delete file"
  66. opts =
  67. method : "delete"
  68. uri: @_buildUrl(project_id, file_id)
  69. timeout:fiveMinsInMs
  70. request opts, (err, response)->
  71. if err?
  72. logger.err err:err, project_id:project_id, file_id:file_id, "something went wrong deleting file from filestore"
  73. callback(err)
  74. copyFile: (oldProject_id, oldFile_id, newProject_id, newFile_id, callback)->
  75. logger.log oldProject_id:oldProject_id, oldFile_id:oldFile_id, newProject_id:newProject_id, newFile_id:newFile_id, "telling filestore to copy a file"
  76. opts =
  77. method : "put"
  78. json:
  79. source:
  80. project_id:oldProject_id
  81. file_id:oldFile_id
  82. uri: @_buildUrl(newProject_id, newFile_id)
  83. timeout:fiveMinsInMs
  84. request opts, (err)->
  85. if err?
  86. logger.err err:err, oldProject_id:oldProject_id, oldFile_id:oldFile_id, newProject_id:newProject_id, newFile_id:newFile_id, "something went wrong telling filestore api to copy file"
  87. callback(err)
  88. _buildUrl: (project_id, file_id)->
  89. return "#{settings.apis.filestore.url}/project/#{project_id}/file/#{file_id}"