Edited at

jQuery 拡張子の無い画像ファイルを表示させる

More than 1 year has passed since last update.

画像ファイルを拡張子無しで格納する、簡易画像アップローダーで、

アイコン画像のアップロード後にデータベースに以下のような情報を格納できるようにしてみました。


JSONデータ定義

[

{
"badge_id": 27,
"badge_name": "おめでとう", //タイトル
"file_name": "おめでとう.svg", //アップロードファイル名
"img_path": "d9c5f2a7e5f24a31b3d10a785", //格納ファイル名
"mtype": "image/svg+xml", //MIME-Type
"file_size": 8192,
"upd_date": "2018-04-28"
}
]

拡張子無しでもブラウザのURLバーに直リンを入れると表示できるので、試しに<img>タグで表示させてみましたが、拡張子無しの画像は表示できませんでした。

どうやら<img>タグで表示させるにはMIME-Typeを関連付けしてデータの判別ができるようにしなければならないようです。

そこでひと手間かけます。

XMLHttpRequest()でファイルを動的にロードし、MIME-Typeを付与してからURL.createObjectURL()を使って一時的なURLを作り出します。


コード

$("document").ready( function() {

//データベースからファイル情報を読み込む
$.ajax({ 'url': "../json/get_badge.cgi", 'type': "post"})
.done(function(data){
var objBadges = JSON.parse(data); //JSONをパース
var baseUrl = "../img/badge/"; //画像ファイルのベースディレクトリ
for(var i=0; i<objBadges.length; i++){
//ファイルをXHRでロード
var xhr = new XMLHttpRequest();
xhr.open('GET', baseUrl + objBadges[i].img_path);
xhr.responseType = "arraybuffer";
xhr.json = objBadges[i]; //イベント内で参照できるようにオブジェクトにJSONデータを添付
xhr.onload = function() {
//ファイルのロード完了したらBlobURL化("blob:http://~~~")
var blob_url = URL.createObjectURL(
new Blob([new Uint8Array(this.response)], {
'type': this.json.mtype //MIME-Typeを付与
})
);
$("<img/>", {
'src': blob_url, //BlobURLをソースにセット
'class': "badges",
'alt': this.json.badge_name, //
'badge_id': this.json.badge_id, // あとで使いやすいように要素に情報を入れておく
'filename': this.json.file_name //
}).on('load', function() {
URL.revokeObjectURL(blob_url); //表示されブラウザがキャッシュしたらURLオブジェクトを破棄する
}).appendTo(".flame")
};
xhr.send();
}
});
});

追記:

画像を使い回すとなるとタグにURL直打ちが不便なので<div>タグにしてしまい、CSSで画像IDごとにbackground-imageを定義してみました。


divタグに変更

//<head>セクションに<style>を挿入しておく

$("<style/>", {
'type': 'text/css',
'id': 'badge_img_style'
}).appendTo("head");

//~~~~中略~~~~~~

$("<div/>", {
'class': "badges",
'badge_id': this.json.badge_id //画像IDのみに変更
}).on('load', function() {
URL.revokeObjectURL(blob_url); //表示が完了したら破棄する
}).appendTo(".flame");

//CSSを動的に定義
$("#badge_img_style").append(
".badges[badge_id='" + this.json.badge_id + "']{background-image: url(" + blob_url + ")}"
);


CSSで使えるようになればロード時に画像を表示させる必要はなくなるので<div>の挿入は、任意のイベントで追加できるのですが、URL.revokeObjectURL()を呼ばなければならないため、何かしらのonloadイベントを呼ぶ要素が必要になるのが悩みどころ。