загрузка файла в куски с помощью html5

Я пытаюсь загрузить файл в куски с помощью API файлов html5, а затем повторно собрать его на стороне сервера в php. Я загружаю видео, но когда я объединять файлы на стороне сервера, размер увеличивается, и он становится недопустимым файлом. Обратите внимание, что приведенный ниже код html5 работает только в браузере. Протестировано в Chrome 9, так как это использует функцию среза файла API. Может ли кто-нибудь меня направить на это? благодаря

Источник PHP

<?php $target_path = "uploads/"; $tmp_name = $_FILES['fileToUpload']['tmp_name']; $size = $_FILES['fileToUpload']['size']; $name = $_FILES['fileToUpload']['name']; $target_file = $target_path . basename($name); $complete = "complete.mov"; $com = fopen("uploads/".$complete, "ab"); error_log($target_path); // Open temp file $out = fopen($target_file, "wb"); if ( $out ) { // Read binary input stream and append it to temp file $in = fopen($tmp_name, "rb"); if ( $in ) { while ( $buff = fread( $in, 1048576 ) ) { fwrite($out, $buff); fwrite($com, $buff); } } fclose($in); fclose($out); } fclose($com); ?> 

Источник HTML

 <!DOCTYPE html> <html> <head> <title>Upload Files using XMLHttpRequest</title> <script type="text/javascript"> window.BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder; function sendRequest() { var blob = document.getElementById('fileToUpload').files[0]; const BYTES_PER_CHUNK = 1048576; // 1MB chunk sizes. const SIZE = blob.size; var start = 0; var end = BYTES_PER_CHUNK; while( start < SIZE ) { var chunk = blob.slice(start, end); uploadFile(chunk); start = end; end = start + BYTES_PER_CHUNK; } } function fileSelected() { var file = document.getElementById('fileToUpload').files[0]; if (file) { var fileSize = 0; if (file.size > 1024 * 1024) fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB'; else fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB'; document.getElementById('fileName').innerHTML = 'Name: ' + file.name; document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize; document.getElementById('fileType').innerHTML = 'Type: ' + file.type; } } function uploadFile(blobFile) { //var file = document.getElementById('fileToUpload').files[0]; var fd = new FormData(); fd.append("fileToUpload", blobFile); var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress, false); xhr.addEventListener("load", uploadComplete, false); xhr.addEventListener("error", uploadFailed, false); xhr.addEventListener("abort", uploadCanceled, false); xhr.open("POST", "upload.php"); xhr.onload = function(e) { alert("loaded!"); }; xhr.send(fd); //alert("oen over"); } function uploadProgress(evt) { if (evt.lengthComputable) { var percentComplete = Math.round(evt.loaded * 100 / evt.total); document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%'; } else { document.getElementById('progressNumber').innerHTML = 'unable to compute'; } } function uploadComplete(evt) { /* This event is raised when the server send back a response */ alert(evt.target.responseText); } function uploadFailed(evt) { alert("There was an error attempting to upload the file."); } function uploadCanceled(evt) { xhr.abort(); xhr = null; //alert("The upload has been canceled by the user or the browser dropped the connection."); } </script> </head> <body> <form id="form1" enctype="multipart/form-data" method="post" action="upload.php"> <div class="row"> <label for="fileToUpload">Select a File to Upload</label><br /> <input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"/> <input type="button" value="cancel" onClick="uploadCanceled();"/> </div> <div id="fileName"></div> <div id="fileSize"></div> <div id="fileType"></div> <div class="row"> <input type="button" onclick="sendRequest();" value="Upload" /> </div> <div id="progressNumber"></div> </form> </body> </html> 

Я попытался решить эту проблему и нашел следующие вещи, которые, надеюсь, будут вам полезны:

1) Функция JS, которую вы используете для нарезки файла, устарела. Я запускаю Chrome v14, и консоль не узнала его. Я должен был изменить это до этого, прежде чем я смог сделать что-нибудь:

 var chunk = blob.webkitSlice(start, end); 

2) Я экспериментировал с гораздо меньшими файлами (около 10 МБ), но имел схожие проблемы – мое видео всегда искажалось после загрузки. Когда я сравнивал оригинал и «копию», я заметил одну особенность: казалось, что части файла были просто перепутаны – все было там, но в неправильном порядке.

Я подозреваю, что одна из проблем, с которой сталкивается ваша текущая программа, не принимает мер, чтобы убедиться, что файлы собраны в правильном порядке. Я считаю, что происходит то, что ваш JS запускает uploadFile несколько раз, не дожидаясь завершения предыдущих загрузок, и сервер пытается собрать файлы в том порядке, в котором он получен, но это не тот же порядок, в котором отправляются файлы ,

Я смог доказать это, заставив ваш код работать (несколько модифицированный, взломанный вместе, как доказательство концепции), назначив каждому файлу порядковый номер по мере его получения, а затем после того, как все части были получены в порядке их сборки. После этого я смог воспроизвести свой видеофайл после его загрузки.

Я думаю, вам придется принять аналогичную меру. Получите все фрагменты файлов, а затем соберите их или, по крайней мере, убедитесь, что принимаете необходимые меры для их упорядочивания. Я не уверен, почему ваши файлы будут расти в размерах (я действительно наблюдал это явление на ранней стадии), поэтому я подозреваю, что это просто какой-то причудливый побочный эффект, в противном случае не синхронизация фрагментов файлов.

Одна из трудностей, с которой вы сразу столкнетесь, заключается в том, что объект Blob в Javasacript не поддерживает изменение или установку имени файла, поэтому вы не можете на стороне клиента предоставить ему уникальный идентификатор. То, что я сделал, как простая работа, заключалось в следующем:

  var i = 1; while( start < SIZE ) { var chunk = blob.webkitSlice(start, end); uploadFile(chunk, i); i++; start = end; end = start + BYTES_PER_CHUNK; } function uploadFile(blobFile, part) { .... xhr.open("POST", "test.php?num=" + part); .... } 

Как вы можете догадаться на стороне сервера, я просто использую эту переменную GET для назначения идентификатора и использую это как основу для любой другой обработки, которая должна быть выполнена на сервере.

В любом случае, это напрямую не затрагивает проблему увеличения размера файла, поэтому я могу только надеяться, что это поможет вам; Мне любопытно узнать, что еще вы узнали!

Привет, я проверил ваш php-файл. Я добавил к нему некоторый код последовательности. И изменил атрибут filename и удалил создание файла dubbel. Вот.

 <?php session_start(); if ($_SESSION['newsession'] == false and $_SESSION['TypeUser'] == 'Admin' ){ $target_path = "../uploads/"; $tmp_name = $_FILES['fileToUpload']['tmp_name']; $size = $_FILES['fileToUpload']['size']; $name = $_FILES['fileToUpload']['name']; $name2 = $_GET['filename']; $target_file = $target_path.$name; $complete =$target_path.$name2; $com = fopen($complete, "ab"); error_log($target_path); // Open temp file //$out = fopen($target_file, "wb"); //if ( $out ) { // Read binary input stream and append it to temp file $in = fopen($tmp_name, "rb"); if ( $in ) { while ( $buff = fread( $in, 1048576 ) ) { // fwrite($out, $buff); fwrite($com, $buff); } } fclose($in); //} //fclose($out); fclose($com); }else{ echo'you are not logged in.'; } ?> 

Для части html я изменил способ загрузки многостраничных файлов. Я помещал тему в список, и один за другим я ее загрузил. Вот код.

 <script type="text/javascript" > function uploadchange() { var input = document.getElementById("file"); var ul = document.getElementById("uploadlist"); while (ul.hasChildNodes()) { ul.removeChild(ul.firstChild); } for (var i = 0; i < input.files.length; i++) { var li = document.createElement("li"); thefilesize = input.files[i].fileSize||input.files[i].size; if (thefilesize > 1024 * 1024){ thefilesize = (Math.round(thefilesize * 100 / (1024 * 1024)) / 100).toString() + 'MB'; }else{ thefilesize = (Math.round(thefilesize * 100 / 1024) / 100).toString() + 'KB'; } li.innerHTML = input.files[i].name + " " + thefilesize ; ul.appendChild(li); } if(!ul.hasChildNodes()) { var li = document.createElement("li"); li.innerHTML = 'No Files Selected'; ul.appendChild(li); } sendRequest(); } window.BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder; function sendRequest() { var blob = document.getElementById('file').files[0]; var BYTES_PER_CHUNK = 1048576; // 1MB chunk sizes. var SIZE = blob.size; var start = 0; var end = BYTES_PER_CHUNK; window.uploadcounter=0; window.uploadfilearray = []; document.getElementById('progressNumber').innerHTML = "Upload: 0 % "; while( start < SIZE ) { var chunk = blob.slice(start, end); window.uploadfilearray[window.uploadcounter]=chunk; window.uploadcounter=window.uploadcounter+1; start = end; end = start + BYTES_PER_CHUNK; } window.uploadcounter=0; uploadFile(window.uploadfilearray[window.uploadcounter],document.getElementById('file').files[0].name); } function fileSelected() { var file = document.getElementById('fileToUpload').files[0]; if (file) { var fileSize = 0; if (file.size > 1024 * 1024) fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB'; else fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB'; document.getElementById('fileName').innerHTML = 'Name: ' + file.name; document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize; document.getElementById('fileType').innerHTML = 'Type: ' + file.type; } } function uploadFile(blobFile,filename) { var fd = new FormData(); fd.append("fileToUpload", blobFile); var xhr = new XMLHttpRequest(); xhr.addEventListener("load", uploadComplete, false); xhr.addEventListener("error", uploadFailed, false); xhr.addEventListener("abort", uploadCanceled, false); xhr.open("POST", "./system/upload2.php?filename="+filename); xhr.onload = function(e) { window.uploadcounter=window.uploadcounter+1; if (window.uploadfilearray.length > window.uploadcounter ){ uploadFile(window.uploadfilearray[window.uploadcounter],document.getElementById('file').files[0].name); var percentloaded2 = parseInt((window.uploadcounter/window.uploadfilearray.length)*100); document.getElementById('progressNumber').innerHTML = 'Upload: '+percentloaded2+' % '; }else{ document.getElementById('progressNumber').innerHTML = "File uploaded"; loadXMLDoc('./system/loaddir.php?url='+ window.currentuploaddir); } }; xhr.send(fd); } function uploadComplete(evt) { /* This event is raised when the server send back a response */ if (evt.target.responseText != ""){ alert(evt.target.responseText); } } function uploadFailed(evt) { alert("There was an error attempting to upload the file."); } function uploadCanceled(evt) { xhr.abort(); xhr = null; //alert("The upload has been canceled by the user or the browser dropped the connection."); } </script> <LINK HREF="./system/link.css" REL="stylesheet" TYPE="text/css"> </head> <body> <div id="fileselector"> <div id="containerback"> </div> <div id="dirlijst"> </div> <div id="container"> <h1>Upload file</h1> <br /> <form name="form1" onSubmit="return uploadFile();" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype="multipart/form-data"> <div id="progressNumber"></div> <input type="file" id="file" multiple name="uploads[]" style="visibility:hidden" onChange="uploadchange();"> <a href="#" onClick="document.getElementById('file').click();return false"><img src="system/iconfilemanager/upload.png" alt="upload file"></a> <div id="uploadlist"> </div> </form> </div> 

Обновленный ответ

В chrome ==> Функция Slice принимает второй параметр как длину.

В FF ==> Функция Slice принимает второй параметр как конец.

примеры кода

 fileorblob.slice(startingPosition, length) //for chrome fileorblob.slice(startingPosition, end)//for FF 

webkitslice and mozslice устарели, вместо этого используют собственный "slice()" .

BlobBuilder также устарел использовать Blob constructor .

Ресурсы:

http://updates.html5rocks.com/2012/06/Don-t-Build-Blobs-Construct-Them

https://developer.mozilla.org/en-US/docs/Web/API/Blob

Чтение файлов как фрагментов и загрузка

Функция Slice принимает второй параметр как длину. Где, когда mozSlice принимает второй параметр как конец

Согласно документации PHP, fread занимает длину в байтах, а не в битах. Вы пытались использовать 1000000 вместо 1048576?