Загрузка файла с помощью php-вызова ajax
У меня есть кнопка, и 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 answers
AJAX не предназначен для загрузки файлов. Откройте новое окно со ссылкой для загрузки в качестве адреса или выполните document.location = ...
.
Очень простое решение с использованием jQuery:
На стороне клиента:
$('.act_download_statement').click(function(e){
e.preventDefault();
form = $('#my_form');
form.submit();
});
И на стороне сервера убедитесь, что вы отправили правильный заголовок Content-Type
, чтобы браузер знал, что это вложение, и загрузка начнется.
@joe: Большое спасибо, это было хорошее предупреждение!
У меня была немного более сложная проблема: 1. отправка AJAX-запроса с данными POST, чтобы сервер создал ZIP-файл 2. получение ответа обратно 3. загрузите ZIP-файл
Вот как я это сделал (используя jQuery для обработки запроса AJAX):
-
Первоначальный запрос на отправку:
var parameters = { pid : "mypid", "files[]": ["file1.jpg","file2.jpg","file3.jpg"] }
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 = $('
<iframe/>
',{'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);
"Запрос/URL" обрабатывает создание почтового индекса (не по теме, поэтому я не буду публиковать полный код) и возвращает следующий объект 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);
}
}
Я добился этого с помощью скрытого 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'
Работает как заклинание.
Вы не можете загрузить файл напрямую через ajax.
Вы можете поместить ссылку на страницу с URL-адресом вашего файла (возвращенным из вызова ajax) или другим способом - использовать скрытый iframe
и динамически задавать URL-адрес источника этого iframe
. Таким образом, вы можете загрузить файл без обновления страницы.
Вот код
$.ajax({
url : "yourURL.php",
type : "GET",
success : function(data) {
$("#iframeID").attr('src', 'downloadFileURL');
}
});