LocalFileWriter.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. const fs = require('fs')
  2. const uuid = require('node-uuid')
  3. const path = require('path')
  4. const Stream = require('stream')
  5. const { callbackify, promisify } = require('util')
  6. const logger = require('logger-sharelatex')
  7. const metrics = require('metrics-sharelatex')
  8. const Settings = require('settings-sharelatex')
  9. const { WriteError } = require('./Errors')
  10. module.exports = {
  11. promises: {
  12. writeStream,
  13. deleteFile
  14. },
  15. writeStream: callbackify(writeStream),
  16. deleteFile: callbackify(deleteFile)
  17. }
  18. const pipeline = promisify(Stream.pipeline)
  19. async function writeStream(stream, key) {
  20. const timer = new metrics.Timer('writingFile')
  21. const fsPath = _getPath(key)
  22. logger.log({ fsPath }, 'writing file locally')
  23. const writeStream = fs.createWriteStream(fsPath)
  24. try {
  25. await pipeline(stream, writeStream)
  26. timer.done()
  27. logger.log({ fsPath }, 'finished writing file locally')
  28. return fsPath
  29. } catch (err) {
  30. await deleteFile(fsPath)
  31. logger.err({ err, fsPath }, 'problem writing file locally')
  32. throw new WriteError({
  33. message: 'problem writing file locally',
  34. info: { err, fsPath }
  35. }).withCause(err)
  36. }
  37. }
  38. async function deleteFile(fsPath) {
  39. if (!fsPath) {
  40. return
  41. }
  42. logger.log({ fsPath }, 'removing local temp file')
  43. try {
  44. await promisify(fs.unlink)(fsPath)
  45. } catch (err) {
  46. if (err.code !== 'ENOENT') {
  47. throw new WriteError({
  48. message: 'failed to delete file',
  49. info: { fsPath }
  50. }).withCause(err)
  51. }
  52. }
  53. }
  54. function _getPath(key) {
  55. if (key == null) {
  56. key = uuid.v1()
  57. }
  58. key = key.replace(/\//g, '-')
  59. return path.join(Settings.path.uploadFolder, key)
  60. }