Github:Download
関連記事:使い方(当blog)
GitHubにある右下のDownload Zipからダウンロードして、ローカルホスト上に解凍。
jquery-ui.htmlをローカルホスト上で実行。
適当なjpgファイルをドラッグ・アンド・ドロップし、startを押します。
アップロード自体が成功しているか確認する
server/php/filesを確認します。この中にファイルがアップロードされていれば、
アップロード自体は成功していることになります。
このアップロードフォルダは、どこで定義されているでしょうか?
それは、server/php/index.phpです。
では、filesフォルダではなく、files2にアップロード先を変えてみましょう。
アップロード先を変える(optionsの使い方)
次のファイルが、ファイルのアップロードや取得をするためのサーバーサイドのコアファイルです。
server/php/UploadHandler.php
アップロード先は、このファイルの「options」で規定されています。
function __construct($options = null, $initialize = true, $error_messages = null) {
$this->options = array(
'script_url' => $this->get_full_url().'/',
'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/',
'upload_url' => $this->get_full_url().'/files/',
ただ、このファイルを直接書き換えるのは、問題があります。
何故なら、バージョンアップに対応できなくなるからです。
そこで、このスクリプトではなく、前段階のindex.phpを書き換えます。
server/php/index.php
index.phpで次のようにオプションを設定します。
$options=array(
'upload_dir' => 'files2/',
'upload_url' => 'アップロードするurl/files2'
);
これでもいいですが、UploadHandler.phpに倣って、少し複雑にします。
こうすれば、アップロードURLも自動取得できます。
error_reporting(E_ALL | E_STRICT);
/*=================================
= myOptions =
=================================*/
class myOptions{
function get_server_var($id) {
return isset($_SERVER[$id]) ? $_SERVER[$id] : '';
}
function get_full_url() {
$https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0;
return
($https ? 'https://' : 'http://').
(!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : '').
(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME'].
($https && $_SERVER['SERVER_PORT'] === 443 ||
$_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))).
substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/'));
}
function uploadDir(){
return dirname($this->get_server_var('SCRIPT_FILENAME'));
}
function uploadUrl(){
return $this->get_full_url();
}
}
$myOptions=new myOptions();
$upDirName='files2';
$upDir='/'.$upDirName.'/';
$options=array(
'upload_dir' => $myOptions->uploadDir().$upDir,
'upload_url' => $myOptions->uploadUrl().$upDir,
);
/*----- End of myOptions ------*/
require('UploadHandler.php');
$upload_handler = new UploadHandler($options);
これで、アップロード先がfiles2に変更されました。
日本語のファイルに対応させる
上記のようにオプションで多くの設定が変更できますが、
日本語ファイル名には対応していません。
ファイルのアップロードファイル名に日本語を利用することは、
あまり良いことではありません。
あまり良いことではありません。
普通はデータベースを利用して、ファイル名と対応付ける、
エンコードをする、等をします。
エンコードをする、等をします。
ですが、今回は、使い方を学ぶため、単純にアップロードファイル名を日本語対応にします。
日本語のアップロードで問題が発生するのは、アップロード処理でしょうか、
それとも表示処理でしょうか。あるいは両方かもしれません。
試しに、実際にアップロードしたファイルとサムネイルの名前を、
windowsならエクスプローラー、macならファインダー上で変更してみます。
windowsならエクスプローラー、macならファインダー上で変更してみます。
すると、正しく日本語で表示され、サムネイルも見ることが出来ました。
というわけで、アップロード処理に問題があったことが分かりました。
ソースを眺めていくと、455行目でbasenameが使われています。
これは現段階のPHPのバージョンにおいて、日本語処理に問題があります。
これは現段階のPHPのバージョンにおいて、日本語処理に問題があります。
そこで、index.phpで次のようにbasenameを修正します。
require('UploadHandler.php');
から
$upload_handler = new UploadHandler($options);
から
$upload_handler = new UploadHandler($options);
までを、次のように変更します。
require('UploadHandler.php');
require('UploadHandler.php');
class myHandler extends UploadHandler{
function my_basename($str) {
$temp = substr(strrchr("/$str",'/'),1);
return $temp;
}
}
protected function trim_file_name($file_path, $name, $size, $type, $error,
$index, $content_range) {
$name = trim($this->my_basename(stripslashes($name)), ".\x00..\x20");
if (!$name) {
$name = str_replace('.', '-', microtime(true));
}
if (strpos($name, '.') === false &&
preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) {
$name .= '.'.$matches[1];
}
if (function_exists('exif_imagetype')) {
switch(@exif_imagetype($file_path)){
case IMAGETYPE_JPEG:
$extensions = array('jpg', 'jpeg');
break;
case IMAGETYPE_PNG:
$extensions = array('png');
break;
case IMAGETYPE_GIF:
$extensions = array('gif');
break;
}
if (!empty($extensions)) {
$parts = explode('.', $name);
$extIndex = count($parts) - 1;
$ext = strtolower(@$parts[$extIndex]);
if (!in_array($ext, $extensions)) {
$parts[$extIndex] = $extensions[0];
$name = implode('.', $parts);
}
}
}
return $name;
}
}
$upload_handler = new myHandler($options);
上記コードは、UploadHandlerを継承させ、
trim_file_nameメソッド内のbasename関数をmy_basenameで置換えています。
そして、
$upload_handler = new Handler($options);
を
$upload_handler = new myHandler($options);
として変更しています。
これでアップロードに関しては、日本語ファイルに対応できました。
trim_file_nameメソッド内のbasename関数をmy_basenameで置換えています。
そして、
$upload_handler = new Handler($options);
を
$upload_handler = new myHandler($options);
として変更しています。
これでアップロードに関しては、日本語ファイルに対応できました。
自動アップロードする
デフォルトでは、手動アップロードですが、これを自動アップロードに変更します。
ルートディレクトリにあるjquery-ui.htmlを編集します。
</body>タグの前に、次のコードを追加します。
<script>
$('#fileupload').fileupload({
autoUpload: true
});
</script>
これでファイルをドラッグ・アンド・ドロップしたら自動でアップロードされるようになりました。
他にどのような設定ができるか知るには、Options(公式:英語)を御覧ください。
ルートディレクトリにあるjquery-ui.htmlを編集します。
</body>タグの前に、次のコードを追加します。
<script>
$('#fileupload').fileupload({
autoUpload: true
});
</script>
これでファイルをドラッグ・アンド・ドロップしたら自動でアップロードされるようになりました。
他にどのような設定ができるか知るには、Options(公式:英語)を御覧ください。
アップロードしたものを先頭に追加する
さきほどの自動アップロードのコードに、prependFiles:trueを追記します。
<script>
$('#fileupload').fileupload({
autoUpload: true,
prependFiles: true
});
</script>
これでドラッグ・アンド・ドロップするとファイルが先頭に追加されます。
同じ名前のファイルを複数アップロードしてみてください。
連番ファイルとして追加されていきます。
<script>
$('#fileupload').fileupload({
autoUpload: true,
prependFiles: true
});
</script>
これでドラッグ・アンド・ドロップするとファイルが先頭に追加されます。
同じ名前のファイルを複数アップロードしてみてください。
連番ファイルとして追加されていきます。
ですが、ブラウザを更新してみてください。
並び順がファイル名順(1→9、a→Z、あ→ん)に変わってしまいました。
何故、アップロード直後と更新後の並び順が違うのでしょうか。
何故、アップロード直後と更新後の並び順が違うのでしょうか。
POSTとGETの処理の違い
アップロード直後は、UploadHandler.phpにおいて、
function post() が実行されます。
それに対して、ブラウザ更新後は、
function get()が実行されます。
これは、161行目のinitialize()メソッドで指定されています。
最終的にはfunction generate_response()メソッドで
json形式に変換され出力される点は同じですが、
post()メソッドは、そのメソッド処理において、
アップロードされたファイル名を直接、配列に入れて、returnします。
(具体的には、$files[]=...以降の部分です。)
一方、get()メソッドはfunction get_file_objects()メソッド内において、
scandir関数を使用し、アップロードされたファイル一覧を取得して、returnします。
そして最終的に、jquery.fileupload-ui.jsにおいて、
返されたjson形式データを、画面上に表示します。
ブラウザ更新後は、なぜ更新日付順にならないのか
返されたjson形式データには、ファイルの更新日時は含まれていません。
また、表示処理においても、更新日付処理はありません。
そのため、更新日付順に表示されません。
PHPスクリプトからどういうデータが返されているか見るには、
http://localhost/jQuery-File-Upload/server/php/index.php
にアクセスしてください。
あるいは、開発コンソールを利用します。
開発コンソールは、ブラウザがchromeの場合、
次のキーを押すと表示されます。
windowsならF12
Macならcommand+option+i
開発コンソールを開き、「Network」→「php/」の部分をクリック→「Preview」をクリックします。
そうすると、server/php/index.phpから返されるjson形式のデータを見ることが出来ます。
ブラウザ更新後のファイルの並び順を変更する(実装)
更新日付順に並び替えるには、2つの方法があります。
1つは、返されるjson形式データに、ファイルの更新日時を追加して、
それを元に並び替える方法。
もう一つは、返されるjson形式データの並び自体をソートする方法です。
ここでは、2つ目の方法を取ることにします。
PHPには、filetimeという、ファイルの更新日付を取得する関数があります。
これを、UploadHandler.phpのget_file_objectsメソッドに追加します。
先ほど追加したmyHandlerクラスに、次のメソッドを追加してください。
なお、my_scandirは、このサイトにあるコードを使用しました。
function my_scandir($dir) {
$ignored = array('.', '..', '.svn', '.htaccess');
$files = array();
foreach (scandir($dir) as $file) {
if (in_array($file, $ignored)) continue;
$files[$file] = filemtime($dir . '/' . $file);
}
arsort($files);
$files = array_keys($files);
return ($files) ? $files : false;
}
protected function get_file_objects($iteration_method = 'get_file_object') {
$upload_dir = $this->get_upload_path();
if (!is_dir($upload_dir)) {
return array();
}
return array_values(array_filter(array_map(
array($this, $iteration_method),
$this->my_scandir($upload_dir)
)));
}
これで、ファイル名に関係なく、新しく追加したものが上に表示されます。
アップロードしたファイルを削除する
通常、Deleteボタンを押して個別削除をしたり、一括削除をすることが出来ます。ですが、405エラーで削除できない場合があります。
これは、サーバーが「DELETE」メソッドを処理できないためです。
そのようなサーバーでも削除できるようにするためには、
次のコードをOptionに追加します。
$options=array(
'upload_dir' => $myOptions->uploadDir().$upDir,
'upload_url' => $myOptions->uploadUrl().$upDir,
'delete_type' => 'POST'
);
ですが、ブラウザーを更新すると、ファイルが削除できていません。
前出のbasenameの日本語バグのためです。
index.phpで、basenameをまとめて変更します。
class myHandler extends UploadHandler{
function my_basename($str) {
$temp = substr(strrchr("/$str",'/'),1);
return $temp;
}
protected function get_version_param() {
return isset($_GET['version']) ? $this->my_basename(stripslashes($_GET['version'])) : null;
}
protected function get_file_name_param() {
$name = $this->get_singular_param_name();
return isset($_GET[$name]) ? $this->my_basename(stripslashes($_GET[$name])) : null;
}
protected function get_file_names_params() {
$params = isset($_GET[$this->options['param_name']]) ?
$_GET[$this->options['param_name']] : array();
foreach ($params as $key => $value) {
$params[$key] = $this->my_basename(stripslashes($value));
}
return $params;
}
protected function trim_file_name($file_path, $name, $size, $type, $error,
$index, $content_range) {
$name = trim($this->my_basename(stripslashes($name)), ".\x00..\x20");
if (!$name) {
$name = str_replace('.', '-', microtime(true));
}
if (strpos($name, '.') === false &&
preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) {
$name .= '.'.$matches[1];
}
if (function_exists('exif_imagetype')) {
switch(@exif_imagetype($file_path)){
case IMAGETYPE_JPEG:
$extensions = array('jpg', 'jpeg');
break;
case IMAGETYPE_PNG:
$extensions = array('png');
break;
case IMAGETYPE_GIF:
$extensions = array('gif');
break;
}
if (!empty($extensions)) {
$parts = explode('.', $name);
$extIndex = count($parts) - 1;
$ext = strtolower(@$parts[$extIndex]);
if (!in_array($ext, $extensions)) {
$parts[$extIndex] = $extensions[0];
$name = implode('.', $parts);
}
}
}
return $name;
}
function my_scandir($dir) {
$ignored = array('.', '..', '.svn', '.htaccess');
$files = array();
foreach (scandir($dir) as $file) {
if (in_array($file, $ignored)) continue;
$files[$file] = filemtime($dir . '/' . $file);
}
arsort($files);
$files = array_keys($files);
return ($files) ? $files : false;
}
protected function get_file_objects($iteration_method = 'get_file_object') {
$upload_dir = $this->get_upload_path();
if (!is_dir($upload_dir)) {
return array();
}
return array_values(array_filter(array_map(
array($this, $iteration_method),
$this->my_scandir($upload_dir)
)));
}
}
これで、日本語ファイル名の削除もできるようになりました。
レイアウトを変更する
基本はテーブルレイアウトになっています。
まずはこれを、divに変えてみましょう。
trとtd、table、tbody、すべてをdivに変更します。
tableをdivに変更した次の行に、jqeuryによってデータが流し込まれます。
<!-- The template to display files available for download -->
<div role="presentation"><div class="files"></div></div>
ここを変更して、gridContainerというIDを付加します。
<!-- The table listing the files available for upload/download -->
<div role="presentation" id="gridContainer"><div class="files"></div></div>
そして、次のコードに
<div class="template-download fade">
gridというクラスを追加します。
<div class="template-download fade grid">
次に、cssを追加します。
head内の適当な箇所に、次のコードを記入します。
<link rel="stylesheet" href="css/grid.css">
そして、grid.cssをcssフォルダに追加し、見た目を作成します。
grid.css
#gridContainer {
margin: 0 auto 25px;
position: relative;
padding-bottom: 10px;
overflow: hidden;
}
.grid {
background: #fff;
color:#000000;
box-shadow: 0 1px 3px rgba(34, 25, 25, 0.4);
float: left;
font-size: 12px;
margin: 8px;
min-height: 100px;
padding: 15px;
width: 188px;
}
.grid h2 ,.grid h2 a{
color: #fa3599;
display: block;
font-family: "Donegal One", serif;
font-size: 17px;
margin: 10px 0;
padding: 0 0 5px;
}
テンプレート内のタイトルを変更する
拡張子を取り除き、ファイル名だけに変更してみます。次の行をコメントアウトします
<!-- <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
-->
かわりに、次のコードを追加します。
{%=filetitle=file.name.replace(/.[^.]+$/, "") %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=filetitle%}</a>
これで、「名前.jpg」から「名前」に置き換わりました。
続く(気が向いたら)
始めまして。JQuery File Uploadの使い方について質問させて下さい。
返信削除こちらの記事内に「日本語のファイルに対応させる」という物がありますが、そのままコピーしているのですが
日本語ファイルが文字化けのままになります。
自分でも色々見直しては見たものの、一向に解決しません。
この記事に書かれているprotected function trim_file_name内の記述でどこか間違っている部分があるのでしょうか?