За последние 24 часа нас посетили 21803 программиста и 1013 роботов. Сейчас ищет 691 программист ...

Передача файла через AJAX

Тема в разделе "JavaScript и AJAX", создана пользователем Зингер, 12 сен 2019.

  1. Зингер

    Зингер Активный пользователь

    С нами с:
    20 июл 2017
    Сообщения:
    127
    Симпатии:
    7
    Всем привет. Столкнулся с проблемой передача pdf файла с сервера на скачивание клиенту.
    Код (Javascript):
    1. //Нажатие на кнопку Сохранить
    2. function btn_for_pdf_download_polzovatel_card_click_function() {
    3.     $.ajax({
    4.         type: 'POST',
    5.         url: "../../../ajax/fpdf_function.php",
    6.         xhrFields: {
    7.             responseType: 'blob'
    8.         },
    9.         success: function (data) {
    10.             var a = document.createElement('a');
    11.             var url = window.URL.createObjectURL(data);
    12.             a.href = url;
    13.             a.download = 'report.pdf';
    14.             document.body.append(a);
    15.             a.click();
    16.         }
    17.     });
    18. }
    19. //Конец Нажатие на кнопку Сохранить
    PHP:
    1. //....формирование report.pdf
    2. //.....................................
    3. header('Content-Type: application/octet-stream');
    4. header('Content-Disposition: attachment; filename="report.pdf"');
    5. readfile('report.pdf');
    Здесь при нажатии на кнопку, должно предлагаться сохранить файл. Но, почему то не работает.
     
  2. Зингер

    Зингер Активный пользователь

    С нами с:
    20 июл 2017
    Сообщения:
    127
    Симпатии:
    7
    Вот что выдает мне отладчик браузера
    Код (Text):
    1. InvalidStateError: responseText is only available if responseType is '' or 'text'
     
  3. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    ну это да, у тебя же 'blob'

    ****

    и да, это у тебя из Node.js что ли функция вызывается, на сервере? или откуда? //это НЕ риторический вопрос))

    просто вот относительный путь:

    Код (Text):
    1. url: "../../../ajax/fpdf_function.php",
    не совсем понятно относительно чего именно
    --- Добавлено ---
    кароч, подозреваю что ты с путями что-то намудрил))

    но отладку стоит начать вот с чего:

    - передай ему вместо pdf - обычный текст с сервера
    - и соответственно responseType:'blob' измени на 'text' как он хочет - посмотрим что оно скажет)))
     
  4. Зингер

    Зингер Активный пользователь

    С нами с:
    20 июл 2017
    Сообщения:
    127
    Симпатии:
    7
    Сервер вернул кракозябры
    Код (Text):
    1. %PDF-1.3
    2. 3 0 obj
    3. <</Type /Page
    4. /Parent 1 0 R
    5. /Resources 2 0 R
    6. /Contents 4 0 R>>
    7. endobj
    8. 4 0 obj
    9. <</Filter /FlateDecode /Length 325>>
    10. stream
    11. x�}�MK�0������ 1M�o~!��c3m�ݤ������f<Ho    a�yg��b�����p�\@-���<U�#$_$Z�cY�b�r�j�����`!u���[��ɥ1��[�Rz�ר>��_Nm��f��1�Z�H�7�S�or���@�ºy����C�������>T'��wQ�b��cHݬ�v�P�lGF)`�-9
    12. ��O9�����p����7k��YL���;xz�E��w���x�:���]�ys�j��8�3\�})�k�J�e�Q���(�
    13. q;�����/���V�2sm�S��sMt6ut���P�ѥ`)����ʻd
    14. endstream
    --- Добавлено ---
    Может что то с заголовками не то?
     
  5. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Да не, это же он pdf и вернул небось))

    Ладно, не суть, скажи, а ты этот относительный путь относительно чего прописал-то?

    Каков контекст исполнения этой функции?

    Это что - обычный джаваскрипт исполняемый в браузере? А каков урл файла в адресной строке браузера?
     
  6. Зингер

    Зингер Активный пользователь

    С нами с:
    20 июл 2017
    Сообщения:
    127
    Симпатии:
    7
    Относительно файла, в котором JS код. Но даже, если url="fpdf_function.php", т.е. серверный php-скрипт в корне сайта, ситуация не меняется. Если бы дело было в путях, то ajax-метод вообще не работал бы никак. А так мы видим, что что-то возвращается.

    fpdf_function.php- это скрипт, который внутри генерит файл pdf (при помощи класса FPDF), ложит его в папку и отдает клиенту на скачивание.

    php- это серверный скрипт, исполняемый на сервере

    localhost:8080/admin/html_view/html/polzovatel_card.html
     
  7. Зингер

    Зингер Активный пользователь

    С нами с:
    20 июл 2017
    Сообщения:
    127
    Симпатии:
    7
    Максимально упростил задачу. Создал новый простой проект. Все файлы в корне.
    HTML:
    1. <!DOCTYPE html>
    2.     <head>
    3.         <title>Тестовый проект</title>
    4.         <meta charset="UTF-8">
    5.         <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6.         <link href="jquery-ui-1.12.1.custom/jquery-ui.structure.min.css" rel="stylesheet" type="text/css"/>
    7.         <link href="jquery-ui-1.12.1.custom/jquery-ui.min.css" rel="stylesheet" type="text/css"/>
    8.         <link href="jquery-ui-1.12.1.custom/jquery-ui.theme.min.css" rel="stylesheet" type="text/css"/>
    9.         <script src="jquery-ui-1.12.1.custom/external/jquery/jquery.js" type="text/javascript"></script>
    10.         <script src="jquery-ui-1.12.1.custom/jquery-ui.min.js" type="text/javascript"></script>
    11.         <script src="jquery-ui-1.12.1.custom/jquery-ui.js" type="text/javascript"></script>
    12.         <script src="test.js" type="text/javascript"></script>
    13.     </head>
    14.     <body>
    15.         <input type="button" value="Скачать" id="btn_test" />
    16.     </body>
    17. </html>
    18.  
    Код (Javascript):
    1. $(document).ready(function () {
    2.     $('#btn_test').button();
    3.     $('#btn_test').click(function () {
    4.         $.ajax({
    5.             url: "test_php.php",
    6.             xhrFields: {
    7.                 responseType: "blob"
    8.             },
    9.             success: function (data, status, xhr) {
    10.                 //alert(data);
    11.                 var blob = new Blob([data], {type: 'image/jpg'});
    12.                 var link = document.createElement('a');
    13.                 link.href = window.URL.createObjectURL(blob);
    14.                 link.download = 'test_image.jpg';
    15.                 link.click();
    16.             }
    17.         });
    18.     });
    19. });
    PHP:
    1. <?php
    2. $file_name = 'test_image.jpg';
    3. Header("HTTP/1.1 200 OK");
    4. Header("Connection: close");
    5. Header("Content-Type: application/octet-stream");
    6. Header("Accept-Ranges: bytes");
    7. Header("Content-Disposition: Attachment; filename=".$file_name);
    8. Header("Content-Length: 50000");
    9. readfile($file_name);
    И все равно ничего. Файл не отдается. Что за ...?
     
  8. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Так а если ты напрямую вызываешь test_php.php из браузера - он тебе отдает этот файл?

    Вот так:

    localhost:8080/path-to-file/test_php.php
     
  9. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    Как-то много «лишних», причем в большинстве не самых простых заголовков.
    PHP:
    1. header('Content-Type: application/octet-stream');
    2. header('Content-Disposition: attachment; filename="'.$page['id'].'"');
    3. header('Content-Length: '.strlen($page['content']));
    4. echo $page['content'];
    Результат: http://g09.ru/file.txt
     
  10. Зингер

    Зингер Активный пользователь

    С нами с:
    20 июл 2017
    Сообщения:
    127
    Симпатии:
    7
    Да, напрямую пошло!
    --- Добавлено ---
    Оставил так:
    PHP:
    1. $file_name = 'test_image.jpg';
    2. Header("Content-Type: application/octet-stream");
    3. Header("Content-Disposition: Attachment; filename=".$file_name);
    4. readfile($file_name);
    Напрямую отдает, через AJAX не хочет.
     
  11. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.792
    Симпатии:
    650
    А что AJAX? Тут специальные техники используются вплоть до скрытого фрэйма. Когда-то оставлял на форуме пост на эту тему, но не смог его найти. Посмотри либы вроде filesaver.js и т.п.
     
  12. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Ну, думаю, для начала имеет таки смысл прописать вместо

    Код (Text):
    1. url: "test_php.php",
    полный урл, по которому он тебе отдает этот файл,

    а дальше уже смотреть по ситуации
     
  13. Зингер

    Зингер Активный пользователь

    С нами с:
    20 июл 2017
    Сообщения:
    127
    Симпатии:
    7
    С учетом всех замечаний:
    Код (Javascript):
    1. $(document).ready(function () {
    2.     $('#btn_test').button();
    3.     $('#btn_test').click(function () {
    4.         $.ajax({
    5.             type: 'POST',
    6.             url: "http://test:8080/test_php.php",
    7.             xhrFields: {
    8.                 responseType: "blob"
    9.             },
    10.             success: function (data, status, xhr) {
    11.                 var blob = new Blob([data], {type: xhr.getResponseHeader('Content-Type')});
    12.                 var link = document.createElement('a');
    13.                 link.href = window.URL.createObjectURL(blob);
    14.                 link.download = 'test_image.jpg';
    15.                 link.click();
    16.             }
    17.         });
    18.     });
    19. });
    PHP:
    1. <?php
    2. $file_name = 'test_image.jpg';
    3. Header("Content-Type: application/octet-stream");
    4. Header("Content-Disposition: Attachment; filename=".$file_name);
    5. readfile($file_name);
    Все равно ошибка та же
    Код (Text):
    1. InvalidStateError: responseText is only available if responseType is '' or 'text'.
    Но уже в отладчике браузера размер переданных байт уже соответствует действительности. Сейчас 746Kb, раньше было где то 48б.
     
  14. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Ну как там, решили?
     
  15. Зингер

    Зингер Активный пользователь

    С нами с:
    20 июл 2017
    Сообщения:
    127
    Симпатии:
    7
    Ну в общем-то, так как хотел не получается. Может что то с версией jQuery?
    Решил обойти проблему, следующим образом. При загрузке страницы в php-скрипте формируется pdf-файл и через AJAX-метод отдается имя файла. После удачной обработки (success (name_file){...}) в ссылке формируется href="...".
     
  16. Roman __construct

    Roman __construct Активный пользователь

    С нами с:
    27 апр 2019
    Сообщения:
    1.270
    Симпатии:
    112
    Ага, крутое решение! Респект! Почему бы и нет :)