我使用 msw 来模拟后端响应,以进行自动化前端测试。
我想为用户创建的数据创建导出功能。我正在向所需路由
我一直在寻找适当的方法来实现这一功能,然后发现了
不幸的是,响应没有触发保存对话框,也没有启动下载,但我找不到错误所在。
我想为用户创建的数据创建导出功能。我正在向所需路由
POST
请求,并希望返回一个包含 .csv; .pdf;.xls 文件的响应,应该自动下载。我一直在寻找适当的方法来实现这一功能,然后发现了
Content-Disposition
响应头。不幸的是,响应没有触发保存对话框,也没有启动下载,但我找不到错误所在。
EDIT: After having a few conversations and the somewhat unique circumstances, I settled for creating a ObjectURL for the Blob-Data generated, and force a download with the
window.open()
call.I changed the expected Response in my Handlers and added a corresponding call in my FE.
handlers.js
rest.post('/mock/things/:thingId/export', async (req, res, ctx) => { const docType = req.headers.get('Content-type'); const startDate = req.url.searchParams.get('startDate'); const endDate = req.url.searchParams.get('endDate'); const selected = req.body; const resDataString = 'testName,testLastName,\r\nDaniel,Schaller'; const blob = new Blob([resDataString], { type: docType }); const buffer = await blob.arrayBuffer(); return res( ctx.status(200), ctx.set({ 'content-type': `${docType}`, 'Content-length': buffer.byteLength.toString(), }), ctx.body(buffer), ctx.delay(), ); }),
store-module.js
async exportThings(ctx, exportData) { const { docType, startDate, endDate, selected, } = exportData; const res = await services.exportThingsForStuff(ctx.state.id, docType, startDate, endDate, selected); if (res.data !== undefined) { const dataBLOB = new Blob([res.data], { type: res.headers['content-type'] }); window.open(URL.createObjectURL(dataBLOB)); } },
让我给你展示一下工作流程:
some-component.vue
async submitExport() {
const exportDataFilters = {
docType: this.docType,
startDate: this.startDate,
endDate: this.endDate,
selected: this.selected,
};
const response = await this.$store.dispatch('exportThings', exportDataFilters);
console.log(response);
},
store-module.js
async exportThings(ctx, exportData) {
const {
docType, startDate, endDate, selected,
} = exportData;
return services.exportThingsForStuff(ctx.state.id, docType, startDate, endDate, selected);
},
services.js
export const exportThingsForStuff = async (thingsId, docType, startDate, endDate, pl) => axios.post(`/mock/things/${thingsId}/export`, pl, {
headers: {
'Content-type': docType,
},
params: {
startDate,
endDate,
},
最后是来自handlers.js的MSW响应函数
rest.post('/mock/things/thingId/export', (req, res, ctx) => {
// Vars will be in use to mimic filter behavior, as soon as the download problem is solved
const docType = req.headers.get('Content-type');
const startDate = req.url.searchParams.get('startDate');
const endDate = req.url.searchParams.get('endDate');
const selected = req.body;
// Creating a test string and blobbing it.
const resDataString = 'testName,testLastName,\r\nJoe,Moe';
const blob = new Blob([resDataString], { type: 'text/csv' });
return res(
ctx.status(200),
ctx.set({
'Content-Disposition': 'attachment; filename="things_export.csv"',
'Content-Length': blob.size.toString(),
'Content-Transfer-Encoding': 'binary',
'Content-Type': 'text/csv',
}),
ctx.body(blob),
ctx.delay(),
);
我找不到问题所在,因为响应看起来像预期的一样:
Request URL: http://localhost:8080/mock/things/101/export?startDate=&endDate=
Request Method: POST
Status Code: 200 OK (from service worker)
Referrer Policy: strict-origin-when-cross-origin
RESPONSE HEADERS
content-disposition: attachment; filename="things_export.csv"
content-length: 37
content-transfer-encoding: binary
content-type: text/csv
x-powered-by: msw
ctx.body
而不是 Blob 中? - kettanaitoPOST
的exportThingsForStuff
方法时提供responseType:'blob'
,如下所示:export const exportThingsForStuff = async (thingsId, docType, startDate, endDate, pl) => axios.post(
/mock/things/${thingsId}/export, pl, { headers: { 'Content-type': docType, }, params: { startDate, endDate, }, responseType: 'blob'
。请您尝试一下? - jccampaneroContent-Disposition: attachment
结合使用时,application/octet-stream 应该不是必需的。由于我知道响应数据的给定数据类型,所以在我看来,application/octet-stream 不是正确的选择。 - D.Schaller