gpt4 book ai didi

javascript - 如何下载获取响应作为文件 react

转载 作者:IT王子 更新时间:2023-10-29 03:11:02 26 4
gpt4 key购买 nike

这是actions.js中的代码

export function exportRecordToExcel(record) {
return ({fetch}) => ({
type: EXPORT_RECORD_TO_EXCEL,
payload: {
promise: fetch('/records/export', {
credentials: 'same-origin',
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(function(response) {
return response;
})
}
});
}

返回的响应是一个.xlsx 文件。我希望用户能够将其保存为文件,但没有任何反应。我假设服务器正在返回正确类型的响应,因为在控制台中它说

Content-Disposition:attachment; filename="report.xlsx"

我错过了什么?在reducer中应该做什么?

最佳答案

浏览器技术目前不支持直接从 Ajax 请求下载文件。解决方法是添加一个隐藏表单并在后台提交它以使浏览器触发“保存”对话框。

我正在运行一个标准的 Flux 实现,所以我不确定确切的 Redux(Reducer)代码应该是什么,但我刚刚为文件下载创建的工作流程是这样的......

  1. 我有一个名为 FileDownload 的 React 组件。该组件所做的只是渲染一个隐藏的表单,然后在 componentDidMount 中立即提交表单并调用它的 onDownloadComplete 属性。
  2. 我有另一个 React 组件,我们称它为 Widget,带有一个下载按钮/图标(实际上很多……一个用于表格中的每个项目)。 Widget 有对应的 action 和 store 文件。 Widget 导入 FileDownload
  3. Widget有两个与下载相关的方法:handleDownloadhandleDownloadComplete
  4. Widget 商店有一个名为 downloadPath 的属性。它默认设置为 null。当它的值设置为 null 时,没有正在进行的文件下载,Widget 组件不会呈现 FileDownload 组件。
  5. 单击 Widget 中的按钮/图标会调用 handleDownload 方法,该方法会触发 downloadFile 操作。 downloadFile 操作不会发出 Ajax 请求。它向商店分派(dispatch)一个 DOWNLOAD_FILE 事件,同时发送要下载的文件的 downloadPath。商店保存 downloadPath 并发出更改事件。
  6. 由于现在有一个 downloadPathWidget 将呈现 FileDownload,并传入必要的属性,包括 downloadPath 作为以及 handleDownloadComplete 方法作为 onDownloadComplete 的值。
  7. 当呈现 FileDownload 并使用 method="GET"(POST 也应该有效)和 action={downloadPath} 提交表单时>,服务器响应现在将触发浏览器的目标下载文件的保存对话框(在 IE 9/10、最新的 Firefox 和 Chrome 中测试)。
  8. 紧接着表单提交,onDownloadComplete/handleDownloadComplete 被调用。这会触发另一个 Action ,该 Action 会分派(dispatch)一个 DOWNLOAD_FILE 事件。但是,这次 downloadPath 设置为 null。商店将 downloadPath 保存为 null 并发出更改事件。
  9. 由于不再有 downloadPath FileDownload 组件不会在 Widget 中呈现,世界是一个快乐的地方。

Widget.js - 仅部分代码

import FileDownload from './FileDownload';

export default class Widget extends Component {
constructor(props) {
super(props);
this.state = widgetStore.getState().toJS();
}

handleDownload(data) {
widgetActions.downloadFile(data);
}

handleDownloadComplete() {
widgetActions.downloadFile();
}

render() {
const downloadPath = this.state.downloadPath;

return (

// button/icon with click bound to this.handleDownload goes here

{downloadPath &&
<FileDownload
actionPath={downloadPath}
onDownloadComplete={this.handleDownloadComplete}
/>
}
);
}

widgetActions.js - 仅部分代码

export function downloadFile(data) {
let downloadPath = null;

if (data) {
downloadPath = `${apiResource}/${data.fileName}`;
}

appDispatcher.dispatch({
actionType: actionTypes.DOWNLOAD_FILE,
downloadPath
});
}

widgetStore.js - 仅部分代码

let store = Map({
downloadPath: null,
isLoading: false,
// other store properties
});

class WidgetStore extends Store {
constructor() {
super();
this.dispatchToken = appDispatcher.register(action => {
switch (action.actionType) {
case actionTypes.DOWNLOAD_FILE:
store = store.merge({
downloadPath: action.downloadPath,
isLoading: !!action.downloadPath
});
this.emitChange();
break;

文件下载.js
- 完整、功能齐全的代码可供复制和粘贴
- React 0.14.7 与 Babel 6.x ["es2015", "react", "stage-0"]
- 表单需要是 display: none 这就是“隐藏” className 的作用

import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';

function getFormInputs() {
const {queryParams} = this.props;

if (queryParams === undefined) {
return null;
}

return Object.keys(queryParams).map((name, index) => {
return (
<input
key={index}
name={name}
type="hidden"
value={queryParams[name]}
/>
);
});
}

export default class FileDownload extends Component {

static propTypes = {
actionPath: PropTypes.string.isRequired,
method: PropTypes.string,
onDownloadComplete: PropTypes.func.isRequired,
queryParams: PropTypes.object
};

static defaultProps = {
method: 'GET'
};

componentDidMount() {
ReactDOM.findDOMNode(this).submit();
this.props.onDownloadComplete();
}

render() {
const {actionPath, method} = this.props;

return (
<form
action={actionPath}
className="hidden"
method={method}
>
{getFormInputs.call(this)}
</form>
);
}
}

关于javascript - 如何下载获取响应作为文件 react ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35206589/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com