从完全形成的响应中触发大型文件下载

时间:2017-03-06 23:58:26

标签: node.js express jwt react-redux http-token-authentication

问题

我有一个Node.js端点,可以在使用以下方式访问时正确触发任意大的文件下载:

response.setHeader('Content-disposition', 'attachment; filename=' + fileName);
response.set('Content-Type', 'text/csv');
response.status(200);
result.pipe(response);

其中resulttransform stream,而responseExpress object

直接访问Chrome,Firefox,Internet Explorer等中的终点时,此工作正常。问题出现在尝试点击启用基于令牌的身份验证时的终点时。

从用户的角度来看,当他们点击按钮时,会下载文件。

如何使用请求标题中的正确身份验证令牌使按钮点击此终点并导致文件下载?

一些可能方法的头脑风暴

  1. 当用户点击该按钮时,它会触发由redux-api-middleware处理的操作,该操作会向端点发出GET请求(身份验证令牌会自动包含在其中)请求)。此中间件将响应保存在变量中,该变量由React组件获取。在此React组件中,如果正在使用的浏览器(即Chrome和Opera)支持流,则response.body将存在,因此您可以执行以下操作。

    if (response.body) {
        const csvReader = response.body.getReader();
        const textDecoder = new TextDecoder();
        const processCsvRow = (csvRow) => {
            if (csvRow.done) {
                console.log('Finished downloading file.');
                return Promise.resolve();
            }
    
            // Write to new file for user to download
            console.log(textDecoder.decode(csvRow.value, {stream: true}));
    
            return csvReader.read().then(processCsvRow);
        };
    
        csvReader.read().then(processCsvRow);
    }
    

    使用这种方法,我需要调查如何处理数据,如果它是由非流支持浏览器接收的。

  2. 当用户点击该按钮时,它会触发一个操作,该操作会通过reducer将端点保存到Redux存储中,从而触发React组件创建自动单击的锚标记。

    const link = document.createElement('a');
    document.body.appendChild(link); // Firefox requires the link to be in the body
    link.href = endPoint;
    link.target = '_blank';
    link.click();
    document.body.removeChild(link); // Remove the link when done
    

    其中endPoint是响应文件的终点。

    禁用身份验证时,此方法有效。重新启用身份验证时,必须以某种方式将身份验证令牌注入到锚标记的请求标头中。

  3. 与#2类似,通过构建内置身份验证令牌的HTTP请求来研究模拟锚点击。
  4. 组合来自#1和#2的元素,当用户点击按钮时,会触发一个动作,向端点发送GET请求,返回第二个临时不安全的端点,返回实际的文件响应。将此临时不安全端点传递给#2中的锚标记。
  5. 以某种方式将响应重定向到新标签/窗口。
  6. 将身份验证令牌作为URL参数传递(这是一个安全问题),然后使用#2。
  7. 创建一个新的终点,生成并返回一个新的临时一次性使用仅下载令牌。使用此新端点将临时令牌作为URL参数通过#2传递到原始端点。

1 个答案:

答案 0 :(得分:1)

我现在决定采用方法#7。