JavaScript で動画ファイルのアップロード

26 1月

upload

JavaScript でファイルを送るのに、jQuery.upload というプラグインを使用しているのですが、Moodle 上の、SCORM コンテンツの中で利用できません。SCORM コンテンツは iframe タグの中に表示されるのですが、何が良くないのか,うまく動かない。それで色々と調べている時に、ローカルのファイルの利用の仕方に関する記事を読みました。そこで,方針を変更してプラグインなしの方法を考えてみました。下記にupload用の例をあげます。冒頭のキャプチャー画像のソースです。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Upload Sample</title>
<script type="text/javascript" src="jquery/jquery.min.js"></script>
<!-- クロスドメイン -->
<script src="jquery/xdr.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
$(function() {
$('#ifName').change(function() {
	var target = document.getElementById('videoFrame');
	var movie = this.files[0];
	var reader = new FileReader();
	reader.onloadend = function(){
		target.src = reader.result;
		var formData = new FormData();
		formData.append('base64data', reader.result);
		$.ajax({
			url:'upload_base64.php?',
			type:'post',
			data:formData,
			timeout:600000,
			processData: false,
			contentType: false,
			success:function(tmptext,status){
				alert(tmptext);
			},
			error:function(){
				alert("upload error");
			}
		});
	}; // reader.onloadend
	if (movie) {
		reader.readAsDataURL(movie);		
	} else {
		target.src = '';
	}
});
});
</script>
<input id="ifName" type="file" name="file" style="font-size:13px; height:24px; width:270px; background-color:#ffffff;" >
<video id="videoFrame"  playsinline autoplay controls style="width: 480px; max-height:360px; background-color:#f0f0f0;"></video>
</body>
</html>

ifName という input タグで、ローカルの動画ファイルを選んで、 FileReader オブジェクトで読み込みます。読み込みが完了したら(onloadend)、読み込んだ結果(result)を video タグの src 属性に指定します。これで、動画が再生されます。この result とは 何かというと base64 にエンコードされたテキストデータです。テキストデータであれば、送信するときに特別なことは必要ありません。いつもの送信のやり方で送信できます。下記が受ける方の PHP です。クロスドメイン用のヘッダーが付いています。

<?php
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Headers:*');
header('Access-Control-Allow-Methods:GET, POST, OPTIONS');
header('Content-Type: text/plain');
$base64data = $_POST['base64data'];
$base64data = str_replace(' ', '+', $base64data);
$tmpary = explode('base64,', $base64data);
$movie = base64_decode($tmpary[1]);
$tmpfile = fopen("./temporary/tmpfile","w");
fwrite($tmpfile,$movie);
fclose($tmpfile);
echo 'success';
?>

base64_decode() がかなりメモリーを必要とします。200MB の動画で、1000MB 程度のメモリーを必要とします。PHP へのメモリーの割当を増やして対応しましたが、どちらかというと JavaScript 側で、base64 をバイナリーファイルに変換したほうが良いと思います。あとで検討してみます。