Загрузить файл с помощью запроса ajax
Я хочу отправить "запрос загрузки ajax", когда я нажимаю кнопку, поэтому я попытался таким образом:
JavaScript:
var xhr = new XMLHttpRequest();
xhr.open("GET", "download.php");
xhr.send();
download.php:
<?
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= file.txt");
header("Content-Transfer-Encoding: binary");
readfile("file.txt");
?>
но не работает должным образом, как я могу это сделать? Заранее благодарю
Ответы
Ответ 1
Обновление 27 апреля 2015 г.
Вверх и переход на сцену HTML5 - это атрибут . Он поддерживается в Firefox и Chrome, и скоро появится IE11. В зависимости от ваших потребностей вы можете использовать его вместо запроса AJAX (или используя window.location
), если файл, который вы хотите загрузить, находится в том же месте, что и ваш сайт.
Вы всегда можете сделать запрос AJAX/ window.location
резервным, используя некоторый JavaScript, чтобы проверить, поддерживается ли download
, а если нет, переключая его на вызов window.location
.
Оригинальный ответ
У вас не может быть запрос AJAX, чтобы открыть приглашение загрузки, так как вам физически приходится перемещаться по файлу, чтобы запросить загрузку. Вместо этого вы можете использовать функцию успеха, чтобы перейти к download.php. Это откроет приглашение загрузки, но не изменит текущую страницу.
$.ajax({
url: 'download.php',
type: 'POST',
success: function() {
window.location = 'download.php';
}
});
Даже если это отвечает на вопрос, лучше просто использовать window.location
и полностью исключить запрос AJAX.
Ответ 2
Для этого вам вообще не нужен ajax. Если вы просто установите "download.php" как href на кнопке или, если это не ссылка, используйте:
window.location = 'download.php';
Браузер должен распознавать двоичную загрузку и не загружать фактическую страницу, а просто обслуживать файл как загрузку.
Ответ 3
Чтобы браузер загрузил файл, вам необходимо сделать такой запрос:
function downloadFile(urlToSend) {
var req = new XMLHttpRequest();
req.open("GET", urlToSend, true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download=fileName;
link.click();
};
req.send();
}
Ответ 4
Это возможно. Вы можете загрузить загрузку изнутри функции ajax, например, сразу после создания файла .csv.
У меня есть функция ajax, которая экспортирует базу данных контактов в CSV файл, и сразу после ее завершения автоматически запускает загрузку файла .csv. Итак, после получения ответаText, и все в порядке, я перенаправляю браузер следующим образом:
window.location="download.php?filename=export.csv";
Мой файл download.php выглядит следующим образом:
<?php
$file = $_GET['filename'];
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=".$file."");
header("Content-Transfer-Encoding: binary");
header("Content-Type: binary/octet-stream");
readfile($file);
?>
Нет обновления страницы, и файл автоматически загружается.
ПРИМЕЧАНИЕ. Протестировано в следующих браузерах:
Chrome v37.0.2062.120
Firefox v32.0.1
Opera v12.17
Internet Explorer v11
Ответ 5
Кросс-браузерное решение, протестированное на Chrome, Firefox, Edge, IE11.
В DOM добавьте тег скрытой ссылки:
<a id="target" style="display: none"></a>
Затем:
var req = new XMLHttpRequest();
req.open("GET", downloadUrl, true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var fileName = null;
var contentType = req.getResponseHeader("content-type");
// IE/EDGE seems not returning some response header
if (req.getResponseHeader("content-disposition")) {
var contentDisposition = req.getResponseHeader("content-disposition");
fileName = contentDisposition.substring(contentDisposition.indexOf("=")+1);
} else {
fileName = "unnamed." + contentType.substring(contentType.indexOf("/")+1);
}
if (window.navigator.msSaveOrOpenBlob) {
// Internet Explorer
window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
} else {
var el = document.getElementById("target");
el.href = window.URL.createObjectURL(blob);
el.download = fileName;
el.click();
}
};
req.send();
Ответ 6
Я предпочитаю location.assign(url);
Полный пример синтаксиса:
document.location.assign('https://www.urltodocument.com/document.pdf');
developer.mozilla.org/en-US/docs/Web/API/Location.assign
Ответ 7
Декодирование имени файла из заголовка немного сложнее...
var filename = "default.pdf";
var disposition = req.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1)
{
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1])
filename = matches[1].replace(/['"]/g, '');
}
Ответ 8
Это решение не сильно отличается от приведенного выше, но для меня это работает очень хорошо, и я думаю, что он чист.
Я предлагаю base64 кодировать сторону файлового сервера (base64_encode(), если вы используете PHP) и отправлять данные с кодировкой base64 клиенту
На клиенте вы делаете это:
let blob = this.dataURItoBlob(THE_MIME_TYPE + "," + response.file);
let uri = URL.createObjectURL(blob);
let link = document.createElement("a");
link.download = THE_FILE_NAME,
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
Этот код помещает закодированные данные в ссылку и имитирует щелчок по ссылке, а затем удаляет ее.
Ответ 9
Ваши потребности покрыты window.location('download.php');
Но я думаю, что вам нужно передать файл для загрузки, не всегда загружать один и тот же файл, и поэтому, почему вы используете запрос, один из вариантов - создать файл php, такой же простой, как showfile.php, и выполнить запрос, подобный
var myfile = filetodownload.txt
var url = "shofile.php?file=" + myfile ;
ajaxRequest.open("GET", url, true);
showfile.php
<?php
$file = $_GET["file"]
echo $file;
где file - это имя файла, переданное через Get или Post в запросе, а затем просто перехватывает ответ в функции
if(ajaxRequest.readyState == 4){
var file = ajaxRequest.responseText;
window.location = 'downfile.php?file=' + file;
}
}
Ответ 10
Это может быть поздно, но это может помочь кому-то, кто сталкивается с этим.
Примечание: это не прямой ответ. Это альтернативный способ.
Во-первых, создайте скрытый элемент привязки, цель которого пуста, чтобы открыть ссылку в новом окне.
<a id="hidden-permalink" class="hidden" href="javascript:void(0)" target="_blank">Hidden</a>
Во-вторых, из вашего успешного обратного вызова ajax/javascript. Получите доступ к скрытому тегу привязки и установите новый URL, а затем активируйте его, как будто пользователь обычно щелкает по нему
success: function ( response ) {
$( '#hidden-permalink' ).attr( 'href', response.permalink )[0].click();
}
Спасибо
Ответ 11
есть другое решение для загрузки веб-страницы в ajax. Но я имею в виду страницу, которая должна быть сначала обработана, а затем загружена.
Для начала нужно отделить обработку страницы от загрузки результатов.
1) В вызове ajax выполняются только расчеты страницы.
$.post("CalculusPage.php", { calculusFunction: true, ID: 29, data1: "a", data2: "b" },
function(data, status)
{
if (status == "success")
{
/* 2) In the answer the page that uses the previous calculations is downloaded. For example, this can be a page that prints the results of a table calculated in the ajax call. */
window.location.href = DownloadPage.php+"?ID="+29;
}
}
);
// For example: in the CalculusPage.php
if ( !empty($_POST["calculusFunction"]) )
{
$ID = $_POST["ID"];
$query = "INSERT INTO ExamplePage (data1, data2) VALUES ('".$_POST["data1"]."', '".$_POST["data2"]."') WHERE id = ".$ID;
...
}
// For example: in the DownloadPage.php
$ID = $_GET["ID"];
$sede = "SELECT * FROM ExamplePage WHERE id = ".$ID;
...
$filename="Export_Data.xls";
header("Content-Type: application/vnd.ms-excel");
header("Content-Disposition: inline; filename=$filename");
...
Я надеюсь, что это решение может быть полезным для многих, как и для меня.