Как разрешить пользователю просматривать / загружать полученный файл диалога выбора файла в браузере? - PullRequest
1 голос
/ 02 мая 2019

У меня есть приложение Angular, где пользователи загружают файлы на сервер.Файлы принимаются следующим образом (не связанный код удален):

@Component({
  selector: "app-select-file-button",
  template: `
     <input type="file" (change)="handleInputChange($event)">
  `
})
export class SelectFileButtonComponent {
  @Output() file: EventEmitter<File> = new EventEmitter<File>();

  handleInputChange(e: any) {
    this.file.emit(e.dataTransfer ? e.dataTransfer.files[0] : e.target.files[0]);
  }
}

Так что это обычный выбор файла.После этого у меня есть возможность показать пользователю, какой файл он выбрал, каков размер файла и т. Д.

Однако у меня есть следующий вариант использования.Пользователи могут ошибочно выбрать неправильный файл, и даже видя имя файла и его размер, все равно не понимают его.Поэтому мне нужно иметь возможность показывать содержимое файла пользователем.

Чего я действительно хотел бы избежать, так это реализации сценария, когда пользователь загружает неправильный файл на сервер, а затем видит ссылку назагруженный файл, загружает его, проверяет, понимает ошибку и затем снова загружает правильный файл.

Файлы могут быть разными - pdf, doc, архивы, mp3 файлы большого размера.Я реализовал показ файла в новом iframe:

const reader = new FileReader();

reader.onload = (e: any) => {
  this.base64Url = e.target.result;

  const win = window.open();
  win.document.write('<iframe src="' + this.base64Url + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen download></iframe>');
};

reader.readAsDataURL(file);

В подходе есть две проблемы:

  • во-первых, подход не работает с mp3файлы в Chrome, так как он пытается воспроизвести аудио, но ничего не происходит (другие файлы либо показываются, либо мгновенно загружаются, что хорошо),mp3-файлы могут быть очень большими (около сотен МБ), и они обычно загружаются с мобильных телефонов, чья память может быть ограничена.

Можно ли использовать лучший подход?Если нет, то как заставить браузер загружать mp3-файлы вместо их открытия?Можно ли установить правильное имя файла в кадре?

1 Ответ

0 голосов
/ 02 мая 2019

Я обнаружил, что решение намного проще, чем ожидалось. Главное, что у меня уже есть файловый блоб, поэтому преобразование в base64url не требуется. Кроме того, браузеры блокируют URL-адреса, открытые из кода по умолчанию, поэтому необходимо угловое дезинфицирующее средство:

import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

Ввод дезинфицирующего средства в компонент:

constructor(private _sanitizer: DomSanitizer) {}

Выбор файла html:

<input type="file" (change)="handleInputChange($event)">

Получение файла блоб-кода:

handleInputChange(e: any) {
    this.file = e.dataTransfer ? e.dataTransfer.files[0] : e.target.files[0];
  }

URL создан и обработан:

const w: any = window;
this.url = this._sanitizer.bypassSecurityTrustResourceUrl((w.webkitURL || w.URL).createObjectURL(this.file));

Использование параметра «скачать» в URL (поэтому браузер не пытается открыть файл и просто загружает его с правильным именем):

<a [href]="url" [download]="file.name">{{file.name}}</a>
...