Узел: загрузка zip через запрос, Zip поврежден
Я использую отличную библиотеку Request для загрузки файлов в Node для небольшого инструмента командной строки, над которым я работаю. Запрос отлично работает для извлечения одного файла, без проблем, но он не работает для ZIP.
Например, я пытаюсь загрузить архив Twitter Bootstrap, который находится по адресу:
http://twitter.github.com/bootstrap/assets/bootstrap.zip
Соответствующая часть кода:
var fileUrl = "http://twitter.github.com/bootstrap/assets/bootstrap.zip";
var output = "bootstrap.zip";
request(fileUrl, function(err, resp, body) {
if(err) throw err;
fs.writeFile(output, body, function(err) {
console.log("file written!");
}
}
Я попытался установить кодировку "двоичный" тоже, но не повезло. Фактический размер почтового индекса составляет ~74 КБ, но при загрузке с помощью вышеуказанного кода он составляет ~134 КБ, и при двойном щелчке в Finder, чтобы извлечь его, я получаю сообщение об ошибке:
Невозможно извлечь "bootstrap" в "nodetest" (Ошибка 21 - каталог)
У меня такое ощущение, что это проблема кодирования, но я не уверен, куда идти дальше.
2 ответа
Да, проблема с кодировкой. Когда вы ждете, чтобы закончить весь перевод body
по умолчанию приводится к строке. Ты можешь сказать request
чтобы дать вам Buffer
вместо этого, установив encoding
возможность null
:
var fileUrl = "http://twitter.github.com/bootstrap/assets/bootstrap.zip";
var output = "bootstrap.zip";
request({url: fileUrl, encoding: null}, function(err, resp, body) {
if(err) throw err;
fs.writeFile(output, body, function(err) {
console.log("file written!");
});
});
Еще одним более элегантным решением является использование pipe()
чтобы направить ответ в файл для записи потока:
request('http://twitter.github.com/bootstrap/assets/bootstrap.zip')
.pipe(fs.createWriteStream('bootstrap.zip'))
.on('close', function () {
console.log('File written!');
});
А один лайнер всегда побеждает:)
pipe()
возвращает целевой поток (в данном случае WriteStream), поэтому вы можете прослушать его close
событие, чтобы получить уведомление, когда файл был написан.
Я искал функцию, которая запрашивает zip-файл и извлекает его без создания какого-либо файла на моем сервере, вот моя функция TypeScript, она использует модуль JSZIP и Request:
let bufs : any = [];
let buf : Uint8Array;
request
.get(url)
.on('end', () => {
buf = Buffer.concat(bufs);
JSZip.loadAsync(buf).then((zip) => {
// zip.files contains a list of file
// chheck JSZip documentation
// Example of getting a text file : zip.file("bla.txt").async("text").then....
}).catch((error) => {
console.log(error);
});
})
.on('error', (error) => {
console.log(error);
})
.on('data', (d) => {
bufs.push(d);
})