忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

JavaScript ファイルのダウンロードについて(link, XMLHttpRequest, msSaveBlob)

今回は JavaScript で行う 「ファイルのダウンロード処理」 について説明したいと思います。

「ファイルのダウンロード処理」PDF ファイルテキストファイル および EXCEL ファイル などをユーザにダウンロードさせたいときに行います。



HTMLタグのみでダウンロード

HTMLタグ のみの記述でダウンロードを挿せる方法を説明します。

a タグ (a 要素、アンカータグ) に download 属性が有りますのでそれを記入します。
以下に zipファイル画像ファイル(.png)PDFファイル のダウンロードを行う HTML を示します。
(zipファイル は download の指定が無くてもOKな様です)

<html>
<head>
<meta charset="utf-8">
<title>test download</title>
</head>
<body>
    <h2>test download</h2>
    <p>
        <a href="./test.zip">[test.zip]ファイルをダウンロード</a>
        <br />
        <a href="./test.png" download>[test.png]ファイルをダウンロード</a>
        <br />
        <a href="./test.pdf" download="TEST1.PDF">[test.pdf]ファイルをダウンロード</a>
    </p>
    <br />
</body>
</html>

download 属性の値にファイル名を設定すると、ダウンロード時にローカルのファイル名がそれになります。

HTMLタグJavaScriptの処理に変更

a タグ の処理を JavaScript の処理に置き変えたものが以下の HTML です。

<html>
<head>
<meta charset="utf-8">
<title>test download</title>
<script type="text/javascript">
function doDownload(url, filename) {
    // a タグ生成
    var alink = document.createElement('a');
    alink.download = filename;  // [download] のファイル名
    alink.href = url;           // サーバのファイルのURL
    alink.click();              // クリック実行
    return false;
}
</script>
</head>
<body>
    <h2>test download</h2>
    <p>
        <button onclick="doDownload('./test.zip', 'test.zip');">
            [test.zip]ファイルをダウンロード
        </button>
        <br />
        <button onclick="doDownload('./test.png', 'test.png');">
            [test.png]ファイルをダウンロード
        </button>
        <br />
        <button onclick="doDownload('./test.pdf', 'TEST1.PDF');">
            [test.pdf]ファイルをダウンロード
        </button>
    </p>
    <br />
</body>
</html>



JavaScriptXMLHttpRequestオブジェクトを使った処理に変更

XMLHttpRequestオブジェクトJavaScript で HTTP リクエストを行うための組み込みのブラウザオブジェクトです。 名前の先頭に XML と付いていますが XML形式だけでなく各種のデータを扱うことができるため、ファイルのダウンロードに利用できます。

上記の doDownload 関数を以下の様にして行います。

function doDownload(url, filename) {
    // XMLHttpRequestオブジェクト作成
    var objXML = new XMLHttpRequest();
    objXML.open("GET", url, true);
    // ダウンロードがblobオブジェクトの指定
    objXML.responseType = "blob";
    // ダウンロード完了時の処理関数
    objXML.onload = function (oEvent) {
        // blobオブジェクト
        var objBlob = objXML.response;
        // blobオブジェクトを指すURLオブジェクト
        var objURL = window.URL.createObjectURL(objBlob);
        // リンクを生成し、JavaScriptからクリック
        var objLink = document.createElement("a");
        document.body.appendChild(objLink);
        objLink.href = objURL;
        objLink.download = filename;
        objLink.click();
    };
    // XMLHttpRequestオブジェクトの通信開始
    objXML.send();
}


XML オブジェクトのダウンロード完了時のイベントである onload で受け取った blob データを window.URL.createObjectURL により指定された内容を参照するために使用されるオブジェクトURLが返されるので、 それをリンクタグに設定し仮想的にクリック処理を行います。

ただこの関数は FireFox Chrome は動作しますが IE, Edge では動作しません。
objLink.click(); のところで「アクセスが拒否されました」となって処理ができません。
IE, Edge には navigator.msSaveBlob メソッドを使うと blob データをファイルに登録できる様です。

IE(Internet Explorer), Eageへの対処方法

以下の関数は、ダウンロード処理時に navigator.msSaveBlob メソッドが存在するかを確認して、 存在する場合にはそのメソッドを使用して処理を行う様に変更しました。

function doDownload(url, filename) {
    // XMLHttpRequestオブジェクト作成
    var objXML = new XMLHttpRequest();
    objXML.open("GET", url, true);
    // ダウンロードがblobオブジェクトの指定
    objXML.responseType = "blob";
    // ダウンロード完了時の処理関数
    objXML.onload = function (oEvent) {
        // blobオブジェクト
        var objBlob = objXML.response;
        if (window.navigator.msSaveBlob) {
            // IE, Edge
            window.navigator.msSaveBlob(objBlob, filename);
        }
        else {
            // blobオブジェクトを指すURLオブジェクト
            var objURL = window.URL.createObjectURL(objBlob);
            // リンクを生成し、JavaScriptからクリック
            var objLink = document.createElement("a");
            document.body.appendChild(objLink);
            objLink.href = objURL;
            objLink.download = filename;
            objLink.click();
            //window.URL.revokeObjectURL(file);
        }
    };
    // XMLHttpRequestオブジェクトの通信を開始する
    objXML.send();
}











PR

コメント

コメントを書く