我正在尝试使用tslib中的fetch方法从我在react-typescript应用程序中创建的API下载一些Excel文件。这是下载代码:
export const getBlobCors = url =>
tryAjax<Blob>(
() =>
fetch(url, {
credentials: 'omit',
headers: new Headers({
...getAuthHeader(),
responseType: 'blob'
})
}),
async response => {
if (response.ok) {
const blob = await response.blob()
return blob
} else {
throw new Error(DefaultErrorMsg)
}
}
)
从这里调用此方法:
async function downloadReport(urlData: ReportUrlData) {
const url = reportUrl(urlData)
const blob = await getBlobCors(url)
const blobUrl = window.URL.createObjectURL(blob)
const a = document.createElement('a')
a.style.display = 'none'
a.href = blobUrl
a.download = 'Report.xlsx'
document.body.appendChild(a)
a.click()
setTimeout(() => {
document.body.removeChild(a)
window.URL.revokeObjectURL(blobUrl)
})
}
正如你现在所看到的,文件名是硬编码的a.download = 'Report.xlsx'
,但我需要的是将它分配给api已经返回的文件名。文件名确实存在于响应头中,但当我',试图读取它getBlobCors
方法响应我得到null
回来,实际上response.headers
是空的。
async response => {
if (response.ok) {
const fileName = response.headers.get('Content-Disposition') // null
const headers = response.headers // Headers {}
const blob = await response.blob()
return blob
}
有谁知道如何从响应或任何其他我可以得到它的文件名?
经过几乎整整一天的努力,我找到了解决问题的方法。问题出在我的后端。由于在CORS上使用Fetch API时访问响应头的限制,默认访问只允许预定义的标准头列表,如Content-Type
,Content-Language
,Last-Modified
,Cache-Control
,Expires
和Pragma
。需要在服务器上显式启用任何其他响应标头。在我的例子中,后端是ASP.NET Core,所以我在Startup.cs中添加了自定义CORS策略
services.AddCors(o => o.AddPolicy("WithExposedContentDispositionHeader", builder =>
{
builder
.AllowAnyOrigin()
.WithExposedHeaders("content-disposition");
}));
并在控制器方法上启用此规则
[EnableCors("WithExposedContentDispositionHeader")]
public async Task<IActionResult> GetExcelReport([FromQuery] ReportInput input) {...}