Как правильно загрузить ZIP-файл, используя Node Js, Archiver и Express
Я пытаюсь сжать содержимое двух каталогов и загрузить полученный ZIP-файл. Один каталог содержит файлы.txt, а другой -.jpg. Я использую архиватор для архивирования файлов и запускаю экспресс-фреймворк на узле js. Я склонен думать, что проблема существует на этапе загрузки, так как результирующий архивированный файл, который создается в корне проекта, расширяется, как и ожидалось, однако, когда файл загружается, я получаю "Ошибка 2 - Нет такого файла или каталога. "
app.get('/download',function(req, res){
zipFile = new Date() + "-Backup.zip";
var output = fs.createWriteStream(__dirname +"/backups/"+ zipFile);
var archive = archiver('zip');
output.on('close', function() {
console.log(archive.pointer() + ' total bytes');
console.log('archiver has been finalized and the output file descriptor has closed.');
});
archive.on('error', function(err) {
throw err;
});
archive.pipe(output);
var files1 = fs.readdirSync(__dirname+'/posts');
var files2 = fs.readdirSync(__dirname+'/uploads');
for(var i = 0; i< files1.length; i++){
archive.append(fs.createReadStream(__dirname+"/posts/"+files1[i]), { name: files1[i] });
}
for(var i = 0; i< files2.length; i++){
archive.append(fs.createReadStream(__dirname+"/uploads/"+files2[i]), { name: files2[i] });
}
archive.finalize();
res.download(__dirname + "/backups/" + zipFile, zipFile);
});
zipFile - это глобальная переменная.
Журналы on 'close' запускаются корректно и ошибок не возникает, но файл не откроется после загрузки. Есть ли проблема с заголовками ответа или что-то еще, о чем я не знаю?
Спасибо за помощь.
2 ответа
Я решил свою проблему, используя node-zip в качестве утилиты архивирования.
var zip = require('node-zip')(); // require the node-zip utility
var fs = require('fs'); // I use fs to read the directories for their contents
var zipName = "someArbitraryName.zip"; // This just creates a variable to store the name of the zip file that you want to create
var someDir = fs.readdirSync(__dirname+"/nameOfDirectoryToZip"); // read the directory that you would like to zip
var newZipFolder = zip.folder('nameOfDirectoryToZip'); // declare a folder with the same name as the directory you would like to zip (we'll later put the read contents into this folder)
//append each file in the directory to the declared folder
for(var i = 0; i < someDir.length,i++){
newZipFolder.file(someDir[i], fs.readFileSync(__dirname+"/nameOfDirectoryToZip/"+someDir[i]),{base64:true});
}
var data = zip.generate({base64:false,compression:'DEFLATE'}); //generate the zip file data
//write the data to file
fs.writeFile(__dirname +"/"+ zipName, data, 'binary', function(err){
if(err){
console.log(err);
}
// do something with the new zipped file
}
По сути, то, что происходит, можно разбить на 3 этапа:
- Используйте fs для чтения содержимого каталога, который вы хотите заархивировать.
- Используйте zip.folder, чтобы объявить папку, затем используйте zip.file, чтобы добавить файлы в этот каталог. Я просто использовал цикл for для итеративного добавления каждого файла в каталог, который был прочитан на шаге 1.
- Используйте zip.generate для создания данных файла.zip и запишите его в файл с помощью fs.
Полученный файл можно загрузить или все, что вы хотели бы с ним сделать. Я не видел никаких проблем с использованием этого метода.
Если вы хотите заархивировать более одного каталога, просто повторите шаги 1 и 2 перед zip.generate, создав новую папку zip.folder для каждого каталога.
Просто используйте
archive.on("finish",function(){
res.download(__dirname + "/backups/" + zipFile);
})