从SailsJS后端到React Redux前端管道压缩文件

时间:2017-05-30 01:15:56

标签: javascript reactjs express redux sails.js

我有一个SailsJS后端,我生成一个zip文件,这是我的前端,Redux的React App所要求的。我使用Sagas进行异步呼叫,使用fetch进行请求。在后端,它尝试了类似的东西:

//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文件结束。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

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

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

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

  • res.sendfile:在此之后你不应该致电.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,而不是每次都在运行它们,这是耗费时间和资源的,而且对于大多数用例来说都是不可取的。