Скачать файл (угловой — dotnet)

пожалуйста, объясните мне, я не могу понять, почему все это происходит.
У меня есть конечная точка 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);
    });
  }
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
0
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вторая проблема, о которой вы упомянули, связана с тем, что в сервисе 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();
  };

Большое спасибо за ответ, сегодня проверю этот подход. Но что, если мне нужно отправить параметры на серверную часть? или реализовать загрузку на основе авторизации? где одни пользователи могут скачивать, а другие нет?

Shadi Aslan 05.06.2024 14:28

авторизация осуществляется на бэкенде. (кстати, вы можете упростить свой бэкэнд, просто вернув File(fileStream, «mime-type вашего файла»); он автоматически установит заголовки. Вы также можете просто создать ссылку в своем угловом .html-файле: <a href = " {{filesUrl}}/download?param = {{your_param_value}}&param‌​2 = {{your_param2_valu‌​e}}">Ссылка</a> Вы также можете использовать POST с <form ngNoForm метод = "post" action = "{{filesURL}}/download"> и отправлять параметры как скрытые поля...

browsermator 05.06.2024 19:47

Спасибо @browsermator, это тот ответ, который я искал. Я хотел отправить конфиденциальные данные при запросе файла, но, поскольку HTTP-запрос не работает должным образом, я не знал, как это сделать. Спасибо!

Shadi Aslan 05.06.2024 19:59

Другие вопросы по теме