ボタンをクリックしたときに "ajax download request"を送信したいので、このようにして試しました。
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");
?>
しかし、期待どおりに動作しません、どうすればいいですか。前もって感謝します
更新2015年4月27日
HTML5の登場は、 download attribute です。 FirefoxとChromeでは supported 、そしてもうすぐIE11になるでしょう。あなたのニーズによっては、ダウンロードしたいファイルがあなたのサイトと同じOrigin上にある限り、AJAXリクエストの代わりに(あるいはwindow.location
を使う)使うことができます。
some JavaScript を使用してdownload
がサポートされているかどうかをテストし、サポートされていない場合はwindow.location
を呼び出すように切り替えることで、常にAJAX request/window.location
を代替として使用できます。
元の答え
AJAX要求でダウンロードプロンプトを開くことはできません。ダウンロードを促すにはファイルに移動する必要があるためです。代わりに、成功関数を使用してdownload.phpに移動することができます。これによりダウンロードプロンプトが開きますが、現在のページは変更されません。
$.ajax({
url: 'download.php',
type: 'POST',
success: function() {
window.location = 'download.php';
}
});
これは質問に答えますが、window.location
を使用し、AJAXリクエストを完全に回避することをお勧めします。
これには実際にはajaxはまったく必要ありません。ボタンのhrefとして "download.php"を設定しただけの場合、またはリンクでない場合は次のようにします。
window.location = 'download.php';
ブラウザはバイナリダウンロードを認識し、実際のページをロードするのではなく、単にダウンロードとしてファイルを提供するべきです。
ブラウザにファイルをダウンロードさせるには、次のようにリクエストする必要があります。
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();
}
クロスブラウザソリューション、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();
可能です。たとえば、.csvファイルが作成された直後など、ajax関数内からダウンロードを開始できます。
連絡先のデータベースを.csvファイルにエクスポートするajax関数があり、それが完了すると自動的に.csvファイルのダウンロードが開始されます。だから、私はresponseTextを取得し、すべてがOKであった後、私はこのようにブラウザをリダイレクトします:
window.location="download.php?filename=export.csv";
My 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);
?>
ページの更新はまったく行われず、ファイルは自動的にダウンロードを開始します。
NOTE - 以下のブラウザでテスト済み。
Chrome v37.0.2062.120
Firefox v32.0.1
Opera v12.17
Internet Explorer v11
私はlocation.assign(url);
が好きです
完全な構文例:
document.location.assign('https://www.urltodocument.com/document.pdf');
あなたのニーズはwindow.location('download.php');
でカバーされています
しかし、いつも同じファイルをダウンロードするのではなく、ダウンロードするファイルを渡す必要があると思います。リクエストを使用している理由の1つは、showfile.phpと同じくらい簡単な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;
}
}
この解決策は上記のものとそれほど違いはありませんが、私にとっては非常にうまく機能していて、私はそれがきれいだと思います。
私は、ファイルサーバー側(base64_encode()、PHPを使用している場合)をbase64エンコードし、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);
このコードは、エンコードされたデータをリンクに配置してリンクのクリックをシミュレートしてから削除します。
ajaxでWebページをダウンロードするための別の解決策があります。しかし、最初に処理してからダウンロードする必要があるページを参照しています。
まず、ダウンロード結果からページ処理を切り離す必要があります。
1)ajax呼び出しではページ計算のみが行われます。
$。post( "CalculusPage.php"、{calculus関数:true、ID:29、data1: "a"、data2: "b"}、 function(data 、status) { if(status == "success") { /* 2)答えとして、前の計算を使ったページがダウンロードされます。 。例えば、これはajax呼び出しで計算された表の結果を印刷するページにすることができます。 */ window.location.href = DownloadPage.php + "?ID =" + 29; } } ); [。 //例:CalculusPage.php if(!empty($ _ POST ["calculusFunction"])) { $ ID = $ _POST ["ID"]; $ query = "ExamplePage(data1、data2)の値に挿入する値( '"。$ _ POST ["data1"]。 "'、 '"。 $ _POST ["data2"]。 "')WHERE id ="。$ ID; ... } //たとえば、 DownloadPage.php $ ID = $ _GET ["ID"]; $ sede = "例* WHERE id ="。$ ID; ... $ filename = "Export_Data.xls"; ヘッダー( "Content-Type:application/vnd.ms-Excel"); [ header( "Content-Disposition:inline; filename = $ filename"); ...
私にとってこの解決策が多くの人に役立つことを願っています。
ヘッダからファイル名をデコードするのはもう少し複雑です...
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, '');
}