最新のPHPニュース

IFRAMEを使って非同期にファイルをアップロードするサンプル

2006年12月04日

anyExample.comにて、PHPを用いて作成したIFRAME & JavaScriptによるファイルアップロードのサンプルスクリプトが掲載されています。

通常、Ajax(XMLHttpRequest)を使用して<input type="file">によるファイル送信はできませんが、IFRAMEをうまく活用することで非同期ファイルアップロードが可能になります。

このスクリプトの基本的な構成は以下の通りです。

IFRAMEを設置し、style="display:none;"で非表示にしておきます。

<input type="file"...>を含むフォームを設置し、そのターゲットにIFRAMEのnameを指定する。このinputフィールドのonchangeイベントでファイル拡張子をチェックし、JavaScriptのsubmit()で、ファイル送信を行います。

IFRAME側では、アップロード完了後に親フレームのHTML要素をJavaScriptで書き換えてやることで、ユーザーにアップロードの完了を通知しています。

また、このスクリプトではアップロードしたファイルのログや、ダウンロード用のインフォメーションページも作成してくれます。

使用方法ですが、ファイルを設置しアップロード先のディレクトリを作成します。そして、以下の2点を各自の環境に合わせるだけです。

$upload_dir = "/var/www/anyexample/aeu";  //アップロードするディレクトリ
$web_upload_dir = "/aeu";                     //上記ディレクトリのウェブ上からのURL

以下、スクリプトのサンプルです。

  1  <?php
  2  
  3  $upload_dir 
'C:\data\public_html\up';        //ファイルをアップロードするディレクトリ
  4  
$web_upload_dir "/up";                                    //上記ディレクトリのwebからアクセスする際のURL
  5  
  6  
$tf $upload_dir.'/'.md5(rand()).".test";
  7  
$f = @fopen($tf"w");
  8  
  9  if (
$f == false) {
 10      die(
"Fatal error! {$upload_dir} is not writable. Set 'chmod 777 {$upload_dir}' or something like this");
 11  }
 12  
 13  
fclose($f);
 14  
unlink($tf);
 15  
 16  
//IFRAME用処理
 17  
if (isset($_POST['fileframe']))  {
 18      
$result 'ERROR';
 19      
$result_msg 'No FILE field found';
 20          
 21          
//アップロード処理
 22      
if (isset($_FILES['file'])) {
 23          if (
$_FILES['file']['error'] == UPLOAD_ERR_OK){
 24              
$filename $_FILES['file']['name'];
 25              
move_uploaded_file($_FILES['file']['tmp_name'], $upload_dir.'/'.$filename);
 26              
$result 'OK';
 27          } elseif (
$_FILES['file']['error'] == UPLOAD_ERR_INI_SIZE) {
 28              
$result_msg 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
 29          } else {
 30              
$result_msg 'Unknown error';
 31                  }
 32      }
 33          
 34          
//IFAMEに出力するHTML
 35      
echo '<html><head><title>-</title></head><body>';
 36      echo 
'<script language="JavaScript" type="text/javascript">'."\n";
 37      
//親フレーム要素を操作するJavaScript
 38      
echo 'var parDoc = window.parent.document;';
 39      if (
$result == 'OK') {
 40          echo 
'parDoc.getElementById("upload_status").value = "file successfully uploaded";';
 41          echo 
'parDoc.getElementById("filename").value = "'.$filename.'";';
 42          echo 
'parDoc.getElementById("filenamei").value = "'.$filename.'";';
 43          echo 
'parDoc.getElementById("upload_button").disabled = false;';
 44      } else {
 45          echo 
'parDoc.getElementById("upload_status").value = "ERROR: '.$result_msg.'";';
 46      }
 47  
 48      echo 
"\n".'</script>now uploading!!</body></html>';
 49      exit();
 50  }
 51  
 52  
//アップロード後の説明ファイル作成
 53  
if (isset($_POST['description'])) {
 54      
$filename $_POST['filename'];
 55      
$size filesize($upload_dir.'/'.$filename);
 56      
$date date('r'filemtime($upload_dir.'/'.$filename));
 57      
$description htmlspecialchars($_POST['description']);
 58  
 59  
 60  
//説明用ファイル作成
 61  
$html =<<<END
 62  
<html><head><title>{$filename} [アップロード完了 by IFRAME 非同期ファイルアップローダー]</title></head>
 63  <body>
 64  <h1>
{$filename}</h1>
 65  <p>アップロードファイル情報ページ</p>
 66  <p>Date: 
{$date}</p>
 67  <p>Size: 
{$size} bytes</p>
 68  <p>Description: 
 69  <pre>
{$description}</pre>
 70  </p>
 71  <p><a href="
{$web_upload_dir}/{$filename}" style="font-size: large;">ダウンロード</a><br>
 72  <a href="
{$PHP_SELF}" style="font-size: small;">アップロード画面に戻る</a><br>
 73  <a href="
{$web_upload_dir}/upload-log.html" style="font-size: small;">アップロードログ</a></p>
 74  </body>
 75  </html>
 76  
END;
 77  
 78      
$f fopen($upload_dir.'/'.$filename.'-desc.html'"w");
 79          
fwrite($f$html);
 80      
fclose($f);
 81      
$msg "File {$filename} アップロード完了, <a href='{$web_upload_dir}/{$filename}-desc.html'>インフォメーションページへ</a>";
 82  
 83          
//アップロードログ追記
 84          
$f fopen($upload_dir."/upload-log.html""a");
 85          
fwrite($f"<p>$msg</p>\n");
 86          
fclose($f);
 87  }
 88  
 89  
?>
 90  
<html>
 91  <head>
 92  <title>IFRAME 非同期 ファイルアップローダー サンプル</title>
 93  </head>
 94  <body>
 95  <?php 
 96  
if (isset($msg)) {
 97      echo 
'<p style="font-weight: bold;">'.$msg.'</p>';
 98  }
 99  
?> 
100  <h1>アップロード ファイル:</h1>
101  
102  <form action="<?=$PHP_SELF?>" target="upload_iframe" method="post" enctype="multipart/form-data">
103      <input type="hidden" name="fileframe" value="true">
104      <label for="file">ファイル選択:</label>    <input type="file" name="file" id="file" onChange="jsUpload(this)">
105  </form>
106  
107  <script type="text/javascript">
108  function jsUpload(upload_field) {
109  
110      var re_text = /\.txt|\.xml|\.zip/i;
111      var filename = upload_field.value;
112      //許可ファイル判定
113      if (filename.search(re_text) == -1) {
114          alert("File does not have text(txt, xml, zip) extension");
115          upload_field.form.reset();
116          return false;
117      }
118          
119      upload_field.form.submit();//ファイルを送信
120      document.getElementById('upload_status').value = "uploading file...";
121      upload_field.disabled = true;
122      return true;
123  }
124  </script>
125  
126  <!-- このフレームはアップロード用で表示はしないようにする -->
127  <iframe name="upload_iframe" style="width: 400px; height: 100px; display: none;"></iframe><br>
128  
129  <!-- これは表示用 -->
130  ステータス:<input type="text" name="upload_status" id="upload_status" value="not uploaded" size="64" disabled><br />
131  ファイル名:<input type="text" name="filenamei" id="filenamei" value="none" disabled>
132  
133  <!-- 説明文用 -->
134  <form action="<?=$PHP_SELF?>" method="POST">
135      <input type="hidden" name="filename" id="filename"><br><br>
136      <label for="photo">ファイル説明:</label><br>
137      <textarea rows="5" cols="50" name="description"></textarea><br><br>
138      <input type="submit" id="upload_button" value="save file" disabled>
139  </form>
140  
141  <p><a href="<?=$web_upload_dir?>/upload-log.html?t=<?=time()?>">アップロードログ</a></p>
142  
143  </body>
144  </html>

関連リンク

この記事へのトラックバックURL