overleaf/services/filestore/app/js/FileConverter.js

99 lines
2 KiB
JavaScript
Raw Normal View History

const metrics = require('@overleaf/metrics')
const Settings = require('@overleaf/settings')
2019-12-19 05:41:41 -05:00
const { callbackify } = require('util')
2014-02-14 11:39:05 -05:00
2019-12-19 05:41:41 -05:00
const safeExec = require('./SafeExec').promises
const { ConversionError } = require('./Errors')
2019-12-19 05:41:41 -05:00
const APPROVED_FORMATS = ['png']
const FOURTY_SECONDS = 40 * 1000
const KILL_SIGNAL = 'SIGTERM'
module.exports = {
2019-12-19 05:41:41 -05:00
convert: callbackify(convert),
thumbnail: callbackify(thumbnail),
preview: callbackify(preview),
promises: {
convert,
thumbnail,
2021-07-13 07:04:46 -04:00
preview,
},
2019-12-19 05:41:41 -05:00
}
async function convert(sourcePath, requestedFormat) {
const width = '600x'
return _convert(sourcePath, requestedFormat, [
'convert',
'-define',
`pdf:fit-page=${width}`,
'-flatten',
'-density',
'300',
2021-07-13 07:04:46 -04:00
`${sourcePath}[0]`,
2019-12-19 05:41:41 -05:00
])
}
async function thumbnail(sourcePath) {
const width = '260x'
return convert(sourcePath, 'png', [
'convert',
'-flatten',
'-background',
'white',
'-density',
'300',
'-define',
`pdf:fit-page=${width}`,
`${sourcePath}[0]`,
'-resize',
2021-07-13 07:04:46 -04:00
width,
2019-12-19 05:41:41 -05:00
])
}
2014-02-14 11:39:05 -05:00
2019-12-19 05:41:41 -05:00
async function preview(sourcePath) {
const width = '548x'
return convert(sourcePath, 'png', [
'convert',
'-flatten',
'-background',
'white',
'-density',
'300',
'-define',
`pdf:fit-page=${width}`,
`${sourcePath}[0]`,
'-resize',
2021-07-13 07:04:46 -04:00
width,
2019-12-19 05:41:41 -05:00
])
}
async function _convert(sourcePath, requestedFormat, command) {
if (!APPROVED_FORMATS.includes(requestedFormat)) {
2020-04-30 08:20:40 -04:00
throw new ConversionError('invalid format requested', {
2021-07-13 07:04:46 -04:00
format: requestedFormat,
})
2019-12-19 05:41:41 -05:00
}
2014-02-14 11:39:05 -05:00
2019-12-19 05:41:41 -05:00
const timer = new metrics.Timer('imageConvert')
const destPath = `${sourcePath}.${requestedFormat}`
command.push(destPath)
command = Settings.commands.convertCommandPrefix.concat(command)
try {
await safeExec(command, {
killSignal: KILL_SIGNAL,
2021-07-13 07:04:46 -04:00
timeout: FOURTY_SECONDS,
})
2019-12-19 05:41:41 -05:00
} catch (err) {
throw new ConversionError(
'something went wrong converting file',
{ stderr: err.stderr, sourcePath, requestedFormat, destPath },
err
)
}
2019-12-19 05:41:41 -05:00
timer.done()
return destPath
}