Задать вопрос
@webartisan2

Как реализовать скачивание файла через AJAX?

Здравствуйте
Имеется веб-страница с формой. При нажатии на кнопку, на сервер отправляются данные с помощью jQuery.
Код запроса выглядит так:
$.ajax({
            url : '/download-action',
            type : 'POST',           
            async : false,            
            beforeSend: function(xhr) {
                xhr.setRequestHeader('X-CSRF-TOKEN', $("#token").attr('value'));
            },
            data : JSON.stringify(sources),
            success : function(data) {
                
            }
        });

На сервер данные приходят и обрабатываются. После обработки сервер отдает файл следующим образом(код прописывается в контроллер Laravel):
header("Pragma: public");
header("Content-Type: text/plain; charset=utf-8");
header("Content-Disposition: attachment; charset=utf-8; filename=\"file.txt\"");
header("Content-Transfer-Encoding: binary"); 
header("Content-Length: " . strlen($file_content));
echo $file_content;

При получении ответа приходит обычный текст. Скачивания файла не происходит.
Вопрос:
Как правильно принять файл на стороне клиента, чтобы выполнялось скачивание?
Заранее спасибо!
  • Вопрос задан
  • 18895 просмотров
Подписаться 2 Оценить 1 комментарий
Решения вопроса 3
Через AJAX файл не скачать. Недавно разбирался с этим.
1. На сервере, при получении AJAX-запроса можно подготовить файл и сформировать уникальную ссылку на него, которую отдать в ответе на полученный AJAX-запрос.
2. В браузере, получив ссылку на файл, открыть новое окно
Ответ написан
Комментировать
Возможно поможет https://github.com/PixelsCommander/Download-File-JS
Ответ написан
Комментировать
RubaXa
@RubaXa
Если мы говорим про современные браузеры, то ничего сложного, первым делом
- Web/API/XMLHttpRequest/Sending_and_Receiving_Binar...

Ну, а дальше дело техники, после того как получили файл на клиенте:
// Создаём ссылку на него
const url = URL.createObjectURL(blob);

// А теперь маленький трюк, чтоб скачать
const dummy = document.createElement('a');
dummy.href = url;
dummy.download = 'my-filename.ext';

document.body.appendChild(dummy);
dummy.click(); // Готово


UPD: Совсем забыл, для IE ещё есть методы msSaveBlob/msSaveOrOpenBlob
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
sokollondon
@sokollondon
Как скачать файл после получения его по ajax
Удобно когда файл долго создаётся и нужно показать preloader

Пример при отправке веб-формы
$(function () {
    $('form').submit(function () {
        $('#loader').show();
        $.ajax({
            url: $(this).attr('action'),
            data: $(this).serialize(),
            dataType: 'binary',
            xhrFields: {
                'responseType': 'blob'
            },
            success: function(data, status, xhr) {
                $('#loader').hide();
                // if(data.type.indexOf('text/html') != -1){//Если вместо файла получили страницу с ошибкой
                //     var reader = new FileReader();
                //     reader.readAsText(data);
                //     reader.onload = function() {alert(reader.result);};
                //     return;
                // }
                var link = document.createElement('a'),
                    filename = 'file.xlsx';
                // if(xhr.getResponseHeader('Content-Disposition')){//имя файла
                //     filename = xhr.getResponseHeader('Content-Disposition');
                //     filename=filename.match(/filename="(.*?)"/)[1];
                //     filename=decodeURIComponent(escape(filename));
                // }
                link.href = URL.createObjectURL(data);
                link.download = filename;
                link.click();
            }
        });
        return false;
    });
});

Не обязательный функционал закомментирован для упрощения примера.

Не требуется создавать временные файлы на сервере.

На jQuery v2.2.4 всё работает. На старой версии будет ошибка:
Uncaught DOMException: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'blob').

https://stackoverflow.com/a/60185326/4831608
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы