LargeFileManager.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /* eslint-disable
  2. no-unused-vars,
  3. */
  4. // TODO: This file was created by bulk-decaffeinate.
  5. // Fix any style issues and re-enable lint.
  6. /*
  7. * decaffeinate suggestions:
  8. * DS102: Remove unnecessary code created because of implicit returns
  9. * DS207: Consider shorter variations of null checks
  10. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  11. */
  12. import fs from 'node:fs'
  13. import { randomUUID } from 'node:crypto'
  14. import Path from 'node:path'
  15. import logger from '@overleaf/logger'
  16. import OError from '@overleaf/o-error'
  17. import metrics from '@overleaf/metrics'
  18. import Settings from '@overleaf/settings'
  19. import _ from 'lodash'
  20. import * as HistoryStoreManager from './HistoryStoreManager.js'
  21. import * as HashManager from './HashManager.js'
  22. export function createStub(fsPath, fileId, fileSize, fileHash, callback) {
  23. if (callback == null) {
  24. callback = function () {}
  25. }
  26. callback = _.once(callback)
  27. const newFsPath = Path.join(
  28. Settings.path.uploadFolder,
  29. randomUUID() + `-${fileId}-stub`
  30. )
  31. const writeStream = fs.createWriteStream(newFsPath)
  32. writeStream.on('error', function (error) {
  33. OError.tag(error, 'error writing stub file', { fsPath, newFsPath })
  34. return fs.unlink(newFsPath, () => callback(error))
  35. })
  36. writeStream.on('finish', function () {
  37. logger.debug(
  38. { fsPath, fileId, fileSize, fileHash },
  39. 'replaced large file with stub'
  40. )
  41. return callback(null, newFsPath)
  42. }) // let the consumer unlink the file
  43. const stubLines = [
  44. 'FileTooLargeError v1',
  45. 'File too large to be stored in history service',
  46. `id ${fileId}`,
  47. `size ${fileSize} bytes`,
  48. `hash ${fileHash}`,
  49. '\0', // null byte to make this a binary file
  50. ]
  51. writeStream.write(stubLines.join('\n'))
  52. return writeStream.end()
  53. }
  54. export function replaceWithStubIfNeeded(fsPath, fileId, fileSize, callback) {
  55. if (callback == null) {
  56. callback = function () {}
  57. }
  58. if (
  59. Settings.maxFileSizeInBytes != null &&
  60. fileSize > Settings.maxFileSizeInBytes
  61. ) {
  62. logger.error(
  63. { fsPath, fileId, maxFileSizeInBytes: Settings.maxFileSizeInBytes },
  64. 'file too large, will use stub'
  65. )
  66. return HashManager._getBlobHash(fsPath, function (error, fileHash) {
  67. if (error != null) {
  68. return callback(error)
  69. }
  70. return createStub(
  71. fsPath,
  72. fileId,
  73. fileSize,
  74. fileHash,
  75. function (error, newFsPath) {
  76. if (error != null) {
  77. return callback(error)
  78. }
  79. return callback(null, newFsPath)
  80. }
  81. )
  82. })
  83. } else {
  84. return callback(null, fsPath)
  85. }
  86. }