Возможно ли создать Post запрос для скачивания файла с сайта написаного на Angular?
Есть сайт. С помощью интструмента разработчика и Postman отследил запрос который отправляется при нажатии на загрузку файла. в ответ получаю {"error":false,"status":200} то же самое происходит и при взаимодействии с UI. Но после этого срабатывает blob и файл скачивается. У меня, в лучшем случае сохраняется в файл {"error":false,"status":200}. JS Код запускаю через консоль разработчика в браузере.
файлы генерируются до 30 метров, если запускать через UI, то я вижу, что запрос отрабатывается не сразу. В моем же случае, я мгновенно получаю 200. Из чего делаю вывод, что дело в асинхронности выполнения, но завершить мысль не хватает знаний. Прошу подсказки.
let XHR = new XMLHttpRequest();
let data = {event_name:'file_save_as'};
let link = 'link';
XHR.open( 'POST', link, true );
XHR.responseType = 'blob';
XHR.setRequestHeader('x-csrf-bypass', 'yes');
XHR.setRequestHeader("accept", "application/json");
XHR.setRequestHeader("Content-Type", "application/json");
XHR.onload = function(e) {
if (this.status == 200) {
// Create a new Blob object using the
//response data of the onload object
var blob = new Blob([this.response], {type: 'application/json'});
//Create a link element, hide it, direct
//it towards the blob, and then 'click' it programatically
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
//Create a DOMString representing the blob
//and point the link element towards it
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = 'myFile.txt';
//programatically click the link to trigger the download
a.click();
//release the reference to the file by revoking the Object URL
window.URL.revokeObjectURL(url);
}else{
//deal with your error state here
}
};
XHR.send(JSON.stringify(data));
Ответы (1 шт):
Да, возможно. Подразумевается, что ваш бекенд готов принять POST запрос, обработать его и вернуть в ответ файл с соответствующими заголовками. Здесь опишу только пример решения на angular.
Для начала подготовим небольшой хук для отдачи файла клиенту. В верстке необходимо добавить:
<!-- ХУК -->
<a style="display: none" href="#" #downloadFile target="_blank"></a>
В компоненте вытащим данную ссылку:
@ViewChild('downloadFile') downloadFile: ElementRef;
Также у вас должны быть данные для POST запроса в виде
{field1: value1, field2: value2 ...}
Для этого я использую ReactiveFormsModule:
public form = new FormGroup({
field1: new FormControl(null, []),
field2: new FormControl(null, []),
});
Подробнее можно почитать в документации.
Подготовим сервис, который будет отправлять http запрос и возвращать содержимое файла
@Injectable({
providedIn: 'root',
})
export class ExampleService {
private downloadUrl = 'http://best-beckend.net/file';
constructor(private http: HttpClient) {}
public downloadFile(data): Observable<string> {
return this.http
.post<string>(this.downloadUrl, data, { responseType: 'blob' as 'json' });
}
}
Далее, в компоненте мы напишем вызов метода сервиса и отдачу файла пользователю
downloadFile(): void {
this.service.downloadFile(this.form.value)
.pipe(takeUntil(this.unsubscribe$)) // Не забываем делать отписку
.subscribe(file => {
if (file) {
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(file, 'Имя файла.расширение файла');
} else {
const url = window.URL.createObjectURL(file);
const link = this.downloadFile.nativeElement;
link.href = url;
link.download = 'Имя файла.расширение файла';
link.click();
window.URL.revokeObjectURL(url);
}
});
}