我有一个Node.js端点,当使用以下方法访问时,它可以正确触发任意大的文件下载:
response.setHeader('Content-disposition', 'attachment; filename=' + fileName); response.set('Content-Type', 'text/csv'); response.status(200); result.pipe(response);
结果是transform stream,响应是Express object.
这在直接访问Chrome,Firefox,Internet Explorer等中的终点时工作正常.问题出现在尝试点击启用基于令牌的身份验证时的终点时.
从用户的角度来看,当他们点击按钮时,会下载文件.
如何使用请求标题中的正确身份验证令牌使按钮点击此终点并导致文件下载?
头脑风暴的一些可能的方法
>当用户单击该按钮时,它会触发由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); }
通过这种方法,我需要研究如何在非流支持的浏览器接收数据时处理数据.
>当用户单击该按钮时,它会触发一个操作,该操作通过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是响应文件的终点.
禁用身份验证时,此方法有效.重新启用身份验证时,必须以某种方式将身份验证令牌注入锚标记的请求标头中.
>与#2类似,通过构建内置身份验证令牌的HTTP请求来研究模拟锚点击.
>组合#1和#2中的元素,当用户单击按钮时,会触发一个动作,向端点发送GET请求,返回第二个临时不安全端点,返回实际文件响应.将此临时不安全端点传递给#2中的锚标记.
>以某种方式将响应重定向到新的选项卡/窗口.
>将身份验证令牌作为URL参数传递(这是一个安全问题),然后使用#2.
>创建一个新的端点,生成并返回一个新的临时一次性使用仅下载令牌.使用此新端点将临时令牌作为URL参数通过#2传递到原始端点.