SPIRAL ver.2 おいて、ver.2.18時点では、サイト側にファイルダウンロード機能が実装されていません。(※)
今回は、 DB に保存されているファイルをサイト側でダウンロード可能にするボタンを作ってみました。
ファイルをダウンロードさせる機能を作りたいと思っている方は参考にしてください。
※ 今後のアップデートで実装される可能性があります。
ver.2.19 のアップデートより、レコードリスト・レコードアイテム でファイル型フィールド対応が可能となっております。
変更・改定履歴
-
改定
パワーポイントのファイルがダウンロードできるよう JavaScript 修正
-
変更
HTML(Thymeleaf)の 箇所に PHP のコードが入っていた件、
及び リード文を修正 -
改定
ダウンロードできる拡張子の追加 および、定数をPHP環境変数に変更
-
改定
利用方法の修正箇所の追記
前提
DB からファイルを取得し、ダウンロードボタンを作成します。
DB にファイルのフィールドを追加の上、試してみてください。
サンプルプログラム
PHP<?php //------------------------------ // 設定値用モジュール //------------------------------ define("API_URL", "https://api.spiral-platform.com/v1/"); define("API_KEY", $SPIRAL->getEnvValue("")); define("API_ROLE",$SPIRAL->getEnvValue("")); // ロールによるAPI権限が不要の場合 define("APP_ID",$SPIRAL->getEnvValue("")); define("DB_ID",$SPIRAL->getEnvValue("")); //------------------------------ // ページ内処理 サンプル //------------------------------ $commonBase = CommonBase::getInstance(); // ファイルが入っている レコード情報を取得 // xxx は、レコードIDをセット $data = $commonBase->apiGetCurlAction("apps/".APP_ID."/dbs/".DB_ID."/records/xxx"); if(array_key_exists('status', $data)){ //APIのエラーが発生した場合、APIのレスポンスにstatusが200以外で返ってくるので、statusをチェック if($data["status"] != 200){ $SPIRAL->setTHValue("error", true); $SPIRAL->setTHValue("errorTxt", "エラーが発生しました。"); } }elseif(isset($data["error"])){ // APIの通信自体が失敗した場合 $SPIRAL->setTHValue("error", true); $SPIRAL->setTHValue("errorTxt", print_r($data,true)); }else{ //取得成功時 // 識別名 は、ファイルレコードの識別名 if(isset($data["item"]["識別名"])){ // ファイルのデータを取得(今回はファイル1つの想定) $imgData = $commonBase->apiGetCurlAction(str_replace(API_URL, '', $data["item"]["識別名"][0]["url"])); if($imgData){ // ファイルのデータからファイル名のデータを Thymeleaf に渡す(今回はファイル1つの想定) $SPIRAL->setTHValue("fileName", $data["item"]["識別名"][0]["fileName"]); // 取得したより、base64形式データをHTMLに渡す $SPIRAL->setTHValue("fileData", $imgData); // ファイル名から拡張子を取得 // 拡張子名は小文字で統一し、HTMLに渡す $SPIRAL->setTHValue("extension", substr($data["item"]["識別名"][0]["fileName"], strrpos($data["item"]["識別名"][0]["fileName"], '.') + 1)); }else{ // ファイルデータが取得できない場合 $SPIRAL->setTHValue("error", true); $SPIRAL->setTHValue("errorTxt", "エラーが発生しました。"); } }else{ // ファイルデータが存在しない場合 $SPIRAL->setTHValue("error", true); $SPIRAL->setTHValue("errorTxt", "添付ファイルが存在しません。"); } } //------------------------------ // 共通用モジュール //------------------------------ class CommonBase { /** * シングルトンインスタンス * @var UserManager */ protected static $singleton; public function __construct() { if (self::$singleton) { throw new Exception('must be singleton'); } self::$singleton = $this; } /** * シングルトンインスタンスを返す * @return UserManager */ public static function getInstance() { if (!self::$singleton) { return new CommonBase(); } else { return self::$singleton; } } /** * ver.2 API * @return Result */ function apiGetCurlAction($addUrlPass) { $header = array( "Authorization:Bearer " . API_KEY, "X-Spiral-Api-Version: 1.1", ); if(API_ROLE){ $header = array_merge($header,array("X-Spiral-App-Role: ".API_ROLE)); } $curl = curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_URL, API_URL . $addUrlPass); curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($curl, CURLOPT_TIMEOUT_MS, 10000); $response = curl_exec($curl); if(json_decode($response)){ return json_decode($response, true); }else{ return base64_encode($response); } } }
利用方法
サンプルプログラムは、ページのPHPタブにセットしてください。各設定値をセットしたPHP環境変数を設定する
define("API_KEY", $SPIRAL->getEnvValue("")); define("API_ROLE",$SPIRAL->getEnvValue("")); // ロールによるAPI権限が不要の場合 define("APP_ID",$SPIRAL->getEnvValue("")); define("DB_ID",$SPIRAL->getEnvValue(""));
API_KEY 6行目 |
アカウント管理で発行したAPIキーをセットしたPHP環境変数の変数名 |
---|---|
API_ROLE 7行目 |
アプリロールの識別名をセットしたPHP環境変数の変数名 アプリロールによる権限設定をしない場合は未入力 |
APP_ID 8行目 |
更新するアプリのIDをセットしたPHP環境変数の変数名 |
DB_ID 9行目 |
更新するDBのIDをセットしたPHP環境変数の変数名 |
API_KEY, API_ROLE, APP_ID, DB_ID など複数ページで使用する値は、PHP環境変数への設定を推奨しております。
PHP環境変数の設定方法は、サポートサイト PHP環境変数をご確認ください。
環境変数を使用しない場合は、getEnvValue()を使用せずに下記のように直接記載してください。
define("API_KEY", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); define("API_ROLE", "XXXAppRole"); // アプリロールを使用しない場合は未入力 define("APP_ID", "XXXXX"); define("DB_ID", "XXXXX");
次に34行目から44行目に記載されている、識別名の箇所をダウンロードさせるファイルフィールドの識別名に変更いたします。
識別名変更の箇所は5つあるのでご注意ください。
if(isset($data["item"]["識別名"])){ // ファイルのデータを取得(今回はファイル1つの想定) $imgData = $commonBase->apiGetCurlAction(str_replace(API_URL, '', $data["item"]["識別名"][0]["url"])); if($imgData){ // ファイルのデータからファイル名のデータを Thymeleaf に渡す(今回はファイル1つの想定) $SPIRAL->setTHValue("fileName", $data["item"]["識別名"][0]["fileName"]); // 取得したより、base64形式データをHTMLに渡す $SPIRAL->setTHValue("fileData", $imgData); // ファイル名から拡張子を取得 // 拡張子名は小文字で統一し、HTMLに渡す $SPIRAL->setTHValue("extension", substr($data["item"]["識別名"][0]["fileName"], strrpos($data["item"]["識別名"][0]["fileName"], '.') + 1));
HTML(Thymeleaf)
PHP より渡された値をボタンの引数にセットします。
HTML(Thymeleaf)<th:block th:if="${cp.result.value['error'] != true}"> <span th:text="${cp.result.value['fileName']}"></span><br /> <input style="width: 150px;" type="button" value="ファイルダウンロード" th:onclick="|download('${cp.result.value['fileName']}','${cp.result.value['extension']}','${cp.result.value['fileData']}')|" /> <a style="display:none;" id="downloader" href="#" target="_blank"></a> </th:block> <th:block th:if="${cp.result.value['error'] == true}"> <span>添付がありません。</span> </th:block> <th:block th:if="${cp.result.value['notFound'] == true}"> <span>添付が存在しません。</span> </th:block>
JavaScript
HTML 側から引数で受け取った値をダウンロードする処理を書きます。
拡張子によって、MINEタイプが違います。
サンプルプログラムで対応している拡張子は、下記になります。
「zip」「pdf」「jpg」「png」「pptx」「doc」「xls」「docx」「xlsx」
「ppt」「txt」「TXT」「csv」「CSV」「tsv」「TSV」「svg」「SVG」
// イベント処理で設定している引数と同じ数だけ、関数でも引数をセット function download(fileName,extension,base64){ // BOM の用意(文字化け対策) var mime_ctype = "application/"+extension; if(extension == "pdf" ){ var blob = toBlob('data:application/' + extension + ';base64,' + base64, mime_ctype); }else if(extension == "zip"){ var blob = toBlob(base64, 'application/'+ extension); }else if(extension == "jpg" || extension == "png" || extension == "pptx" ){ var blob = toBlob('data:image/' + extension + ';base64,' + base64, mime_ctype); }else if(extension == "doc" ){ var blob = toBlob('data:application/msword' + ';base64,' + base64, mime_ctype); }else if(extension == "xls" ){ var blob = toBlob('data:application/vnd.ms-excel' + ';base64,' + base64, mime_ctype); }else if(extension == "docx" ){ var blob = toBlob('data:application/vnd.openxmlformats-officedocument.wordprocessingml.document' + ';base64,' + base64, mime_ctype); }else if(extension == "xlsx" ){ var blob = toBlob('data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + ';base64,' + base64, mime_ctype); }else if(extension == "ppt" ){ var blob = toBlob('data:application/vnd.ms-powerpoint' + ';base64,' + base64, mime_ctype); }else if(extension == "txt" || extension == "TXT"){ var blob = toBlob('data:text/plain' + ';base64,' + base64, mime_ctype); }else if(extension == "csv" || extension == "CSV"){ var blob = toBlob('data:text/csv' + ';base64,' + base64, mime_ctype); }else if(extension == "tsv" || extension == "TSV"){ var blob = toBlob('data:text/tab-separated-values' + ';base64,' + base64, mime_ctype); }else if(extension == "svg" || extension == "SVG"){ var blob = toBlob('data:image/svg+xml' + ';base64,' + base64, mime_ctype); }else{ alert("ダウンロードできません。"); return; } var url = (window.URL || window.webkitURL).createObjectURL(blob); // IEはdownload属性が効かないので分岐 if (window.navigator.msSaveOrOpenBlob) { var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'blob'; xhr.onloadend = function() { if(xhr.status !== 200) return; window.navigator.msSaveBlob(xhr.response, fileName); } xhr.send(); } else { var a = document.getElementById('downloader'); a.download = fileName; a.href = url; // ダウンロードリンクをクリックする a.click(); } return; } function toBlob(base64,mime_ctype) { const bin = atob(base64.replace(/^.*,/, '')); const buffer = new Uint8Array(bin.length); for (let i = 0; i < bin.length; i++) { buffer[i] = bin.charCodeAt(i); } // Blobを作成 const blob = new Blob([buffer.buffer], { type: mime_ctype }); return blob; }
不具合やほかのやり方がある等あれば、
下記の「コンテンツに関しての要望はこちら」からご連絡ください。