Скачать файл через php ajax call - PullRequest
31 голосов
/ 12 июля 2011

У меня есть кнопка, и onclick вызовет функцию ajax.

Вот моя функция ajax

function csv(){

    ajaxRequest = ajax();//ajax() is function that has all the XML HTTP Requests

    postdata = "data=" + document.getElementById("id").value;

    ajaxRequest.onreadystatechange = function(){
        var ajaxDisplay = document.getElementById('ajaxDiv');
        if(ajaxRequest.readyState == 4 && ajaxRequest.status==200){
            ajaxDisplay.innerHTML = ajaxRequest.responseText;           
        }
    }

    ajaxRequest.open("POST","csv.php",false);
    ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    ajaxRequest.send(postdata);
}

Я создаю CSV-файл на основе пользовательского ввода. После его создания я хочу, чтобы он запрашивал загрузку или принудительную загрузку (предпочтительно принудительную). Я использую следующий скрипт в конце файла php, чтобы загрузить файл. Если я запускаю этот скрипт в отдельном файле, он работает нормально.

$fileName = 'file.csv';
$downloadFileName = 'newfile.csv';

if (file_exists($fileName)) {
    header('Content-Description: File Transfer');
    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename='.$downloadFileName);
    ob_clean();
    flush();
    readfile($fileName);
    exit;
}
echo "done";

Но если я запускаю его в конце csv.php, он выводит содержимое файла .csv на страницу (в ajaxDiv) вместо загрузки.

Есть ли способ принудительно загрузить файл в конце csv.php?

Ответы [ 5 ]

40 голосов
/ 12 июля 2011

AJAX не для загрузки файлов.Откройте новое окно со ссылкой для загрузки в качестве адреса или выполните команду document.location = ....

.
20 голосов
/ 10 ноября 2012

Очень простое решение с использованием jQuery:

на стороне клиента:

$('.act_download_statement').click(function(e){
    e.preventDefault();
    form = $('#my_form');
    form.submit();
});

и на стороне сервера, убедитесь, что вы отправили обратно правильный заголовок Content-Type, поэтомубраузер узнает вложение и загрузка начнется.

12 голосов
/ 12 июля 2012

@ Джо: Большое спасибо, это было хорошо!

У меня была немного более сложная проблема: 1. отправка AJAX-запроса с данными POST для сервера для создания ZIP-файла 2. получить ответ обратно 3. скачать ZIP файл

Вот как я это сделал (используя JQuery для обработки запроса AJAX):

  1. Первоначальный почтовый запрос:

    var parameters = {
         pid     : "mypid",
       "files[]": ["file1.jpg","file2.jpg","file3.jpg"]
    }</p>
    
    <p>var options = {
       url: "request/url",//replace with your request url
       type: "POST",//replace with your request type
       data: parameters,//see above
       context: document.body,//replace with your contex
       success: function(data){
        if (data) {
            if (data.path) {
                        //Create an hidden iframe, with the 'src' attribute set to the created ZIP file.
                var dlif = $('<code><iframe/></code>',{'src':data.path}).hide();
                //Append the iFrame to the context
                this.append(dlif);
            } else if (data.error) {
                alert(data.error);
            } else {
                alert('Something went wrong');
            }
        }
    }
    };
    $.ajax(options);

«request / url» обрабатывает создание zip (не по теме, поэтому я не буду публиковать полный код) и возвращает следующий объект JSON. Что-то вроде:

 //Code to create the zip file
 //......
 //Id of the file
 $zipid = "myzipfile.zip"
 //Download Link - it can be prettier
 $dlink = 'http://'.$_SERVER["SERVER_NAME"].'/request/download&file='.$zipid;
 //JSON response to be handled on the client side
 $result = '{"success":1,"path":"'.$dlink.'","error":null}';
 header('Content-type: application/json;');
 echo $result;

«Запрос / загрузка» может при необходимости выполнить некоторые проверки безопасности и сгенерировать передачу файла:

$fn = $_GET['file'];
if ($fn) {
  //Perform security checks
  //.....check user session/role/whatever
  $result = $_SERVER['DOCUMENT_ROOT'].'/path/to/file/'.$fn;
  if (file_exists($result)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/force-download');
    header('Content-Disposition: attachment; filename='.basename($result));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($result));
    ob_clean();
    flush();
    readfile($result);
    @unlink($result);
  }

}
9 голосов
/ 25 марта 2012

Я достиг этого с помощью скрытого iframe.Я использую perl, а не php, поэтому просто дам концепцию, а не решение кода.

Клиент отправляет Ajax-запрос на сервер, вызывая генерацию содержимого файла.Это сохраняется как временный файл на сервере, а имя файла возвращается клиенту.

Клиент (javascript) получает имя файла и устанавливает для iframe src некоторый URL, который доставит файл, например:

$('iframe_dl').src="/app?download=1&filename=" + the_filename

Сервер отбрасывает файл, отсоединяет его и отправляет поток клиенту со следующими заголовками:

Content-Type:'application/force-download'
Content-Disposition:'attachment; filename=the_filename'

Работает как чудо.

2 голосов
/ 17 марта 2014

Вы не можете скачать файл напрямую через ajax.

Вы можете поместить ссылку на страницу с URL-адресом вашего файла (возвращенного из вызова ajax) или другим способом - использовать скрытый iframe и установите URL источника этого iframe динамически.Таким образом, вы можете скачать файл без обновления страницы.

Вот код

$.ajax({
    url : "yourURL.php",
    type : "GET",
    success : function(data) {
        $("#iframeID").attr('src', 'downloadFileURL');
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...