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;
}
不具合やほかのやり方がある等あれば、
下記の「コンテンツに関しての要望はこちら」からご連絡ください。