пожалуйста, объясните мне, я не могу понять, почему все это происходит.
У меня есть конечная точка API для загрузки файла по этому URL-адресу: https://localhost:7004/api/Files/download.
Если я вставлю этот URL-адрес в свой браузер и перейду к нему, файл загрузится правильно.
Однако если я обновлю страницу, загрузка не начнется снова.
И когда я говорю «правильная загрузка», я имею в виду, что загрузка делегируется диспетчеру загрузок браузера, и вы можете приостановить или отменить процесс загрузки (для меня это означает, что мой API настроен правильно, но что-то не так, поскольку обновление не загрузится повторно). , только повторная вставка URL-адреса в браузер снова запускает загрузку).
Однако (и это моя основная проблема), когда я пытаюсь загрузить файл в своем угловом приложении, загрузка появляется на вкладке моей сети, и только после того, как весь процесс загрузки там завершен, он делегирует завершенную загрузку браузеру (то есть никакой прогресс никогда не отображается, пока вся загрузка не будет завершена, и это не удобно для пользователя в случае больших файлов, а также моя точка останова в первой строке внутри моего метода подписки срабатывает после завершения всей загрузки, что ничего не значит внутри моей подписки действительно необходимо или делает что-нибудь «const url = window.URL.createObjectURL(res);», я нашел это при отладке моего приложения ofc.
PS Я попробовал и «блок», и «arrayBuffer» в качестве типа ответа в методе get.
вот мой код:
конечная точка дотнета:
private readonly string _filePath = "C:/Users/shadi/Desktop/file.zip";
[HttpGet("download")]
public IActionResult DownloadFile()
{
if (!System.IO.File.Exists(_filePath))
{
return NotFound();
}
var fileName = "file.zip";
var fileStream = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
var fileLength = new FileInfo(_filePath).Length;
Response.Headers.Add("Content-Disposition", $"attachment; filename = {fileName}");
Response.Headers.Add("Content-Length", fileLength.ToString());
Response.Headers.Add("Content-Type", "application/octet-stream");
return new FileStreamResult(fileStream, "application/octet-stream");
}
угловой сервис:
downloadFile(): Observable<Blob> {
const url = `${this.filesUrl}/download`
return this.http.get(url, { responseType: 'blob' });
}
угловая составляющая:
download(): void {
this.fileService.downloadFile().subscribe((res: Blob) => {
const url = window.URL.createObjectURL(res);
const a = document.createElement('a');
a.href = url;
a.download = 'file.zip';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
});
}
Вторая проблема, о которой вы упомянули, связана с тем, что в сервисе Angluar вы сами обрабатываете запрос на получение через httpclient, а не делегируете его браузеру. Затем в вашем компоненте вы реагируете на завершение всего запроса на получение (загрузка полностью завершена).
Чтобы делегировать загрузку браузеру, вы можете пропустить ту часть, где вы запрашиваете файл через http-клиент, и просто создать элемент a
с вашим URL-адресом в виде href
и добавлением атрибута download
.
В вашем компоненте:
download = () => {
const url = this.fileService.filesUrl + '/download';
const link = document.createElement('a');
link.setAttribute('target', '_blank');
link.setAttribute('href', url );
link.setAttribute('download', `file.zip`);
document.body.appendChild(link);
link.click();
link.remove();
};
авторизация осуществляется на бэкенде. (кстати, вы можете упростить свой бэкэнд, просто вернув File(fileStream, «mime-type вашего файла»); он автоматически установит заголовки. Вы также можете просто создать ссылку в своем угловом .html-файле: <a href = " {{filesUrl}}/download?param = {{your_param_value}}¶m2 = {{your_param2_value}}">Ссылка</a> Вы также можете использовать POST с <form ngNoForm метод = "post" action = "{{filesURL}}/download"> и отправлять параметры как скрытые поля...
Спасибо @browsermator, это тот ответ, который я искал. Я хотел отправить конфиденциальные данные при запросе файла, но, поскольку HTTP-запрос не работает должным образом, я не знал, как это сделать. Спасибо!
Большое спасибо за ответ, сегодня проверю этот подход. Но что, если мне нужно отправить параметры на серверную часть? или реализовать загрузку на основе авторизации? где одни пользователи могут скачивать, а другие нет?