mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-08-25 12:23:58 -04:00
a76be7270e
Only show in developer changelog
58 lines
1.6 KiB
JavaScript
58 lines
1.6 KiB
JavaScript
// @ts-check
|
|
const fs = require('fs');
|
|
const {default: axios} = require('axios');
|
|
|
|
let temporaryFileCounter = 0;
|
|
|
|
/**
|
|
* Download a file to `outputPath`. The download is done to a temporary file
|
|
* which is renamed at the end, so that `outputPath` is never left with a
|
|
* partially downloaded (i.e: corrupted) file - even if the download fails
|
|
* or if multiple downloads to the same `outputPath` are attempted.
|
|
*
|
|
* @param {string} url
|
|
* @param {string} outputPath
|
|
* @returns {Promise<void>}
|
|
*/
|
|
const downloadLocalFile = async (url, outputPath) => {
|
|
const temporaryPath = `${outputPath}.${process.pid}-${temporaryFileCounter++}.tmp`;
|
|
try {
|
|
const response = await axios.get(url, {
|
|
responseType: 'stream',
|
|
});
|
|
|
|
await new Promise((resolve, reject) => {
|
|
const writer = fs.createWriteStream(temporaryPath);
|
|
let error = null;
|
|
const onError = err => {
|
|
error = err;
|
|
writer.close();
|
|
reject(err);
|
|
};
|
|
// Watch for errors on the response stream too: they are not forwarded
|
|
// to the writer by `pipe`, and would otherwise leave the promise
|
|
// pending forever.
|
|
response.data.on('error', onError);
|
|
writer.on('error', onError);
|
|
writer.on('close', () => {
|
|
if (!error) {
|
|
resolve(undefined);
|
|
}
|
|
|
|
// No need to call `reject` here, as it will have been called in the
|
|
// 'error' callback.
|
|
});
|
|
response.data.pipe(writer);
|
|
});
|
|
|
|
await fs.promises.rename(temporaryPath, outputPath);
|
|
} catch (error) {
|
|
await fs.promises.unlink(temporaryPath).catch(() => {});
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
downloadLocalFile,
|
|
};
|