[英]Piping zip file from SailsJS backend to React Redux Frontend
I have a SailsJS Backend where i generate a zip File, which was requested by my Frontend, a React App with Redux. 我有一个SailsJS后端,我在其中生成一个zip文件,这是我的前端(带有Redux的React App)请求的。 I'm using Sagas for the Async Calls and fetch for the request.
我正在使用Sagas进行异步调用并提取请求。 In the backend, it tried stuff like:
在后端,它尝试了以下操作:
//zipFilename is the absolute path
res.attachment(zipFilename).send();
or 要么
res.sendfile(zipFilename).send();
or 要么
res.download(zipFilename)send();
or pipe the stream with: 或通过以下方式传递流:
const filestream = fs.createReadStream(zipFilename);
filestream.pipe(res);
on my Frontend i try to parse it with: 在我的前端,我尝试解析为:
parseJSON(response) => {
return response.clone().json().catch(() => response.text());
}
everything i tried ends up with an empty zip file. 我尝试的所有内容都以一个空的zip文件结尾。 Any suggestions?
有什么建议么?
There are various issues with the options that you tried out: 您尝试的选项存在各种问题:
res.attachment
will just set the Content-Type
and Content-Disposition
headers, but it will not actually send anything. res.attachment
只会设置Content-Type
和Content-Disposition
标头,但实际上不会发送任何内容。
You can use this to set the headers properly, but you need to pipe the ZIP file into the response as well. 您可以使用它来正确设置标题,但是您也需要将ZIP文件通过管道传递到响应中。
res.sendfile
: You should not call .send()
after this. res.sendfile
: .send()
不应调用.send()
。 From the official docs' examples: 从官方文档的示例:
app.get('/file/:name', function (req, res, next) { var options = { ... }; res.sendFile(req.params.name, options, function (err) { if (err) { next(err); } else { console.log('Sent:', fileName); } }); });
If the ZIP is properly built, this should work fine and set the proper Content-Type
header as long as the file has the proper extension. 如果正确构建了ZIP,则只要文件具有适当的扩展名,它就可以正常工作并设置适当的
Content-Type
标头。
res.download
: Same thing, you should not call .send()
after this. res.download
:同样,您不应在此之后调用.send()
。 From the official docs' examples: 从官方文档的示例:
res.download('/report-12345.pdf', 'report.pdf', function(err) { ... });
res.download
will use res.sendfile
to send the file as an attachment, thus setting both Content-Type
and Content-Disposition
headers. res.download
将使用res.sendfile
作为附件发送文件,从而设置Content-Type
和Content-Disposition
标头。
However, you mention that the ZIP file is being sent but it is empty, so you should probably check if you are creating the ZIP file properly. 但是,您提到正在发送ZIP文件,但该文件为空,因此您可能应该检查是否正确创建了ZIP文件。 As long as they are built properly and the extension is
.zip
, res.download
should work fine. 只要它们正确构建且扩展名为
.zip
, res.download
应该可以正常工作。
If you are building them on the fly, check this out: 如果要动态构建它们,请检查以下内容:
This middleware will create a ZIP file with multiples files on the fly and send it as an attachment. 该中间件将动态创建一个包含多个文件的ZIP文件,并将其作为附件发送。 It uses
lazystream
and archiver
它使用
lazystream
和archiver
const lazystream = require('lazystream');
const archiver = require('archiver');
function middleware(req, res) {
// Set the response's headers:
// You can also use res.attachment(...) here.
res.writeHead(200, {
'Content-Type': 'application/zip',
'Content-Disposition': 'attachment; filename=DOWNLOAD_NAME.zip',
});
// Files to add in the ZIP:
const filesToZip = [
'assets/file1',
'assets/file2',
];
// Create a new ZIP file:
const zip = archiver('zip');
// Set up some callbacks:
zip.on('error', errorHandler);
zip.on('finish', function() {
res.end(); // Send the response once ZIP is finished.
});
// Pipe the ZIP output to res:
zip.pipe(res);
// Add files to ZIP:
filesToZip.map((filename) => {
zip.append(new lazystream.Readable(() => fs
.createReadStream(filename), {
name: filename,
});
});
// Finalize the ZIP. Compression will start and output will
// be piped to res. Once ZIP is finished, res.end() will be
// called.
zip.finalize();
}
You can build around this to cache the built ZIPs instead of building them on the fly every time, which is time and resource consuming and totally unadvisable for most uses cases. 您可以围绕它进行构建,以缓存已构建的ZIP,而不是每次都在运行中即时构建它们,这既浪费时间和资源,对于大多数用例来说也不可取。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.