Хранилище nodejs multer для удаления файла после сохранения на диск
Я использую хранилище дисков Multer для сохранения файла на диск. Сначала я сохраняю его на диск и выполняю некоторые операции с файлом, а затем загружаю его в удаленное ведро, используя другую функцию и lib. Как только загрузка будет завершена, я хотел бы удалить ее с диска.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
var upload = multer({ storage: storage }).single('file')
и вот как я его использую:
app.post('/api/photo', function (req, res) {
upload(req, res, function (err) {
uploadToRemoteBucket(req.file.path)
.then(data => {
// delete from disk first
res.end("UPLOAD COMPLETED!");
})
})
});
Как я могу использовать функцию удаления diskStorage, чтобы удалить файлы из временной папки? https://github.com/expressjs/multer/blob/master/storage/disk.js#L54
Обновить:
Я решил сделать его модульным и поместить в другой файл:
const fileUpload = function(req, res, cb) {
upload(req, res, function (err) {
uploadToRemoteBucket(req.file.path)
.then(data => {
// delete from disk first
res.end("UPLOAD COMPLETED!");
})
})
}
module.exports = { fileUpload };
5 ответов
Вам не нужно использовать multer
удалить файл и кроме того _removeFile
это частная функция, которую вы не должны использовать.
Вы удалите файл, как обычно, через fs.unlink
, Так что везде, где у вас есть доступ к req.file
Вы можете сделать следующее:
const fs = require('fs')
const { promisify } = require('util')
const unlinkAsync = promisify(fs.unlink)
// ...
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename(req, file, cb) {
cb(null, `${file.fieldname}-${Date.now()}`)
}
})
const upload = multer({ storage: storage }).single('file')
app.post('/api/photo', upload, async (req, res) =>{
// You aren't doing anything with data so no need for the return value
await uploadToRemoteBucket(req.file.path)
// Delete the file like normal
await unlinkAsync(req.file.path)
res.end("UPLOAD COMPLETED!")
})
Мултер не нужен. Просто используйте этот код.
const fs = require('fs')
const path = './file.txt'
fs.unlink(path, (err) => {
if (err) {
console.error(err)
return
}
//file removed
})
Я удалил каталог после загрузки файла с помощью fs-extra
const fs = require('fs-extra');
// after you uploaded to bucket
await fs.remove('uploads/abc.png'); // remove upload dir when uploaded bucket
Чтобы сделать это действительно автоматически на всех маршрутах, я использовал эту стратегию:
когда запрос заканчивается, мы удаляем все загруженные файлы (req.files). Перед этим, если вы хотите сохранить файлы на сервере, вам нужно сохранить их по другому пути.
var express = require('express');
var app = express();
var http = require('http');
var server = http.Server(app);
// classic multer instantiation
var multer = require('multer');
var upload = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, `${__dirname}/web/uploads/tmp/`);
},
filename: function (req, file, cb) {
cb(null, uniqid() + path.extname(file.originalname));
},
}),
});
app.use(upload.any());
// automatically deletes uploaded files when express finishes the request
app.use(function(req, res, next) {
var writeHead = res.writeHead;
var writeHeadbound = writeHead.bind(res);
res.writeHead = function (statusCode, statusMessage, headers) {
if (req.files) {
for (var file of req.files) {
fs.unlink(file.path, function (err) {
if (err) console.error(err);
});
}
}
writeHeadbound(statusCode, statusMessage, headers);
};
next();
});
// route to upload a file
router.post('/profile/edit', access.isLogged(), async function (req, res, next) {
try {
// we copy uploaded files to a custom folder or the middleware will delete them
for (let file of req.files)
if (file.fieldname == 'picture')
await fs.promises.copy(file.path, `${__dirname}/../uploads/user/photo.jpg`);
} catch (err) {
next(err);
}
});
Вы также можете рассмотреть возможность использования MemoryStorage для этой цели, с этим хранилищем файл никогда не сохраняется на диске, а в памяти и автоматически удаляется из памяти после того, как выполнение выходит из блока контроллера, то есть после того, как вы обслужите ответ в большей части случаи.
Когда вы будете использовать этот вариант хранения, вы не получите поля
file.destination
,
file.path
и
file.filename
, вместо этого вы получите поле
file.buffer
который, как следует из названия, является буфером, вы можете преобразовать этот буфер в желаемый формат для выполнения операций, а затем загрузить его с помощью объекта потока.
Большинство популярных библиотек поддерживают потоки, поэтому вы должны иметь возможность использовать поток для загрузки файла напрямую, код для преобразования буфера в поток:
const Readable = require('stream').Readable;
var stream = new Readable();
stream._read = () => { }
stream.push(file.buffer);
stream.push(null);
// now you can pass this stream object to your upload function
Этот подход был бы более эффективным, поскольку файлы будут храниться в памяти, что приведет к более быстрому доступу, но у него есть недостаток, упомянутый в
multer
документация:
ПРЕДУПРЕЖДЕНИЕ. Очень быстрая загрузка очень больших файлов или относительно небольших файлов в большом количестве может привести к тому, что вашему приложению будет не хватать памяти при использовании хранилища памяти.