#javascript #reactjs #typescript #blob #fetch
#javascript #reactjs #typescript #большой двоичный объект #извлечение
Вопрос:
Я пытаюсь загрузить некоторый файл Excel из API, который я создал в своем приложении react-typescript, используя метод выборки из tslib. Вот код загрузки:
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
}
Кто-нибудь знает, как прочитать имя файла из ответа или любого другого, который я могу получить?
Ответ №1:
Потратив на это почти целый день, я нашел способ решить проблему. Проблема была в моем серверной части. Из-за ограничения доступа к заголовкам ответов при использовании Fetch API через CORS, где по умолчанию разрешен доступ только к предопределенному списку стандартных заголовков, таких как Content-Type
, Content-Language
, Last-Modified
, Cache-Control
Expires
Pragma
и,,,,,,,,,,,,,. Любые другие заголовки ответа должны быть включены на сервере явно. В моем случае серверная часть была ASP.NET Ядро, поэтому я добавил пользовательскую политику CORS в Startup.cs
services.AddCors(o => o.AddPolicy("WithExposedContentDispositionHeader", builder =>
{
builder
.AllowAnyOrigin()
.WithExposedHeaders("content-disposition");
}));
И включил это правило в методе контроллера
[EnableCors("WithExposedContentDispositionHeader")]
public async Task<IActionResult> GetExcelReport([FromQuery] ReportInput input) {...}