单击按钮时,我需要从服务器下载文件。
我创建了一个MaterialUI按钮,在其onclick回调中,我调用容器组件已连接的操作。
该操作是异步的,并执行ajax POST:
export const onXlsxClick = () => dispatch => {
const urlParams = {
filters: {
aggregation: 'macro_area',
chart_resolution: '1_hour',
chart_from: '1478080363',
chart_to: '1477993963'
},
labels: ['PROVA1', 'PROVA2'],
series: [
{
label: null,
timestamp: 1478080363,
values: [123, 345]
},
{
label: null,
timestamp: 1477993963,
values: [153, 3435]
}
]
};
return $.ajax({
url:'/rest/export/chart/xlsx',
type: 'POST',
dataType: 'application/json',
contentType: 'application/json',
data: JSON.stringify(urlParams)
})
.done(data => {
console.log('success');
})
.fail(error => {
console.log(error);
});
};
服务器接收请求并通过此REST服务正确处理:
@POST
@Path("xlsx")
@Produces("application/vnd.ms-excel")
public Response getXlsx(ChartExportRequest request) {
ResponseBuilder responseBuilder;
ChartExportRequestDTO reqDto = null;
try {
reqDto = parseDTO(request);
checkRequestDTO(reqDto);
ExportDTO dto = getXlsxProvider().create(reqDto);
responseBuilder = Response.ok(dto.getFile())
.header("Content-disposition", "attachment;filename=" + dto.getFileName());
}
catch(Exception e) {
logger.error("Error providing export xlsx for tab RIGEDI with request [" + (reqDto != null ? reqDto.toString() : null) + "]", e);
responseBuilder = Response.serverError().entity(e.getMessage());
}
return responseBuilder.build();
}
问题是响应正确地到达客户端但是没有任何反应:我希望浏览器显示下载对话框(例如:在chrome中我希望下载的下载栏显示在我的文件中)。
我做错了什么?
答案 0 :(得分:9)
AS根据Nate的回答here,浏览器无法将Ajax请求的响应识别为文件。对于所有Ajax响应,它的行为方式相同。 您需要手动触发下载弹出窗口。
在我的实现中,一旦我在reducer中收到API响应,我就使用filesaverjs来触发下载弹出窗口。
由于FileSaver使用blob来保存文件,我将服务器的响应作为blob发送,将其转换为字符串数组缓冲区,然后使用它来保存我的文件。
中描述了这种方法请在下面找到减速机的示例代码: (根据Redux使用reducer进行状态修改) reducer.js
let fileSaver = require("file-saver");
export default function projectReducer(state = {}, action)
{
let project;
switch (action.type) {
case GET_PROJECT_SUCCESS :
project = Object.assign(action.response.data);
return project;
case EXPORT_AND_DOWNLOAD_DATA_SUCCESS :
let data = s2ab(action.response.data);
fileSaver.saveAs(new Blob([data], {type: "application/octet-stream"}), "test.xlsx");
return state;
}
return state;
}
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}