Ответ 1
Функция Slice принимает второй параметр как длину. Если mozSlice принимает второй параметр как end
Я пытаюсь загрузить файл в куски, используя html5 File API, а затем снова смонтирую его на стороне сервера в php. Я загружаю видео, но когда я объединять файлы на стороне сервера, размер увеличивается, и он становится недопустимым файлом. Обратите внимание, что приведенный ниже код html5 работает только в браузере. Протестировано в Chrome 9, так как это использует функцию среза API файлов. Может ли кто-нибудь меня направить на это? Спасибо
<?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);
?>
<!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>
Функция Slice принимает второй параметр как длину. Если mozSlice принимает второй параметр как end
Я попытался решить эту проблему и нашел следующие вещи, которые, надеюсь, будут вам полезны:
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
устарел, вместо этого используйте native "slice()"
.
BlobBuilder
также не рекомендуется использовать Blob constructor
.
Ресурсы
http://updates.html5rocks.com/2012/06/Don-t-Build-Blobs-Construct-Them
Согласно документации PHP, fread занимает длину в байтах, а не в битах. Вы пытались использовать 1000000 вместо 1048576?