将SailsJS后端的zip文件传输到React Redux前端

问题描述 投票:0回答:1

我有一个SailsJS后端,我在其中生成一个zip文件,这是我的前端(带有Redux的React App)请求的。 我正在使用Sagas进行异步调用并提取请求。 在后端,它尝试了以下操作:

//zipFilename is the absolute path 
res.attachment(zipFilename).send();

要么

res.sendfile(zipFilename).send();

要么

res.download(zipFilename)send();

或通过以下方式传递流:

const filestream = fs.createReadStream(zipFilename);
filestream.pipe(res);

在我的前端,我尝试解析为:

parseJSON(response) => {
  return response.clone().json().catch(() => response.text());
}

我尝试的所有内容都以一个空的zip文件结尾。 有什么建议么?

javascript reactjs express redux sails.js
1个回答
1
投票

您尝试的选项存在各种问题:

  • res.attachment只会设置Content-TypeContent-Disposition标头,但实际上不会发送任何内容。

    您可以使用它来正确设置标题,但是您也需要将ZIP文件通过管道传递到响应中。

  • res.sendfile.send()不应调用.send() 。 从官方文档的示例:

     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); } }); }); 

    如果正确构建了ZIP,则只要文件具有适当的扩展名,它就可以正常工作并设置适当的Content-Type标头。

  • res.download :同样,您不应在此之后调用.send() 。 从官方文档的示例:

     res.download('/report-12345.pdf', 'report.pdf', function(err) { ... }); 

    res.download将使用res.sendfile作为附件发送文件,从而设置Content-TypeContent-Disposition标头。

但是,您提到正在发送ZIP文件,但该文件为空,因此您可能应该检查是否正确创建了ZIP文件。 只要它们正确构建且扩展名为.zipres.download应该可以正常工作。

如果要动态构建它们,请检查以下内容:

该中间件将动态创建一个包含多个文件的ZIP文件,并将其作为附件发送。 它使用lazystreamarchiver

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();
}

您可以围绕它进行构建,以缓存已构建的ZIP,而不是每次都在运行中即时构建它们,这既浪费时间和资源,对于大多数用例来说也不可取。

© www.soinside.com 2019 - 2024. All rights reserved.