| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- import fs from 'node:fs'
- import crypto from 'node:crypto'
- import path from 'node:path'
- import Stream from 'node:stream'
- import { callbackify, promisify } from 'node:util'
- import metrics from '@overleaf/metrics'
- import Settings from '@overleaf/settings'
- import Errors from './Errors.js'
- const { WriteError } = Errors
- export default {
- promises: {
- writeStream,
- deleteFile,
- },
- writeStream: callbackify(writeStream),
- deleteFile: callbackify(deleteFile),
- }
- const pipeline = promisify(Stream.pipeline)
- async function writeStream(stream, key) {
- const timer = new metrics.Timer('writingFile')
- const fsPath = _getPath(key)
- const writeStream = fs.createWriteStream(fsPath)
- try {
- await pipeline(stream, writeStream)
- timer.done()
- return fsPath
- } catch (err) {
- await deleteFile(fsPath)
- throw new WriteError('problem writing file locally', { fsPath }, err)
- }
- }
- async function deleteFile(fsPath) {
- if (!fsPath) {
- return
- }
- try {
- await fs.promises.unlink(fsPath)
- } catch (err) {
- if (err.code !== 'ENOENT') {
- throw new WriteError('failed to delete file', { fsPath }, err)
- }
- }
- }
- function _getPath(key) {
- if (key == null) {
- key = crypto.randomUUID()
- }
- key = key.replace(/\//g, '-')
- return path.join(Settings.path.uploadFolder, key)
- }
|