Загрузить файл через ajax-вызов php

У меня есть кнопка и 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?

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

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

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

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

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

Я сделал это со скрытым 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' 

Работает как шарм.

@joe: Большое спасибо, это был хороший хедз-ап!

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

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

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

     var parameters = { pid : "mypid", "files[]": ["file1.jpg","file2.jpg","file3.jpg"] } 

    var parameters = { pid : "mypid", "files[]": ["file1.jpg","file2.jpg","file3.jpg"] }

    var options = {
    url: "request / url", // заменить URL вашего запроса
    type: «POST», // заменяем ваш тип запроса
    данные: параметры, // см. выше
    context: document.body, // заменить на ваш contex
    успех: функция (данные) {
    if (data) {
    if (data.path) {
    // Создаем скрытый iframe с атрибутом 'src', установленным в созданный ZIP-файл.
    var dlif = $ (' <iframe/> ', {'src': data.path}). hide ();
    // Добавить iFrame в контекст
    this.append (dlif);
    } else if (data.error) {
    оповещения (data.error);
    } else {
    предупреждение («Что-то пошло не так»);
    }
    }
    }
    };
    $ .ajax (варианты);

«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); } } 

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

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

Вот код

 $.ajax({ url : "yourURL.php", type : "GET", success : function(data) { $("#iframeID").attr('src', 'downloadFileURL'); } });