通过XHR上传大型文件失败,Chrome与Firefox兼容

时间:2015-03-11 16:11:52

标签: javascript php google-chrome firefox file-upload

我正在将视频文件上传到我的服务器。文件至少为20MB,有些超过100MB。

为了改善用户体验,我通过JavaScript和XMLHttpRequest上传,这样我就可以显示上传速度和剩余时间。

为避免服务器上的麻烦(例如请求超时和处理时间过长),我在服务器上的小包中提交文件,然后让php脚本重新组装文件。

我的脚本效果很好,有一个奇怪的问题 - 直到现在我才认为这是因为我的ISP。

使用Google Chrome我可以上传最大20MB的文件,没有任何问题。但是任何更大的错误都会产生错误:例如我的100MB文件不会向服务器发送任何内容 - 第二个包永远不会到达。在我的50MB文件中,它发生在大约47%之后,第7个包。而另一个文件甚至不发送第一个包。

我重新启动了我的计算机,并且每个文件的位置/包的编号都相同 - 尽管该位置与其他失败的文件相比没有任何共同点。

如果你尝试在其中一个失败的软件包之后启动它并不重要,比如说如果我从#8开始,如果7失败 - 它将继续失败。如果我忽略错误(而不是再次尝试),它将以空块的形式发送文件的其余部分。

我已经尝试过不同的互联网连接,但我不得不在那里使用firefox。它工作得很好。所以我在我的机器上安装了firefox,BAM就像魅力一样,正确发送100MB文件。

Chrome上可能出现什么问题?



$(document).on('click','#video_upload',function(evt){
	uploadProcess('vod_video_file');
});


function toBlob(text)
{
	var data = new ArrayBuffer(text.length);
	var ui8a = new Uint8Array(data, 0);

	for (var i = 0; i < text.length; i++) ui8a[i] = (text.charCodeAt(i) & 0xff);

	if(typeof window.Blob == "function")
	{
		 var blob = new Blob([data]);
	}else{
		 var bb = new (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)();
		 bb.append(data);
		 var blob = bb.getBlob();
	}
	return blob;
}

function splitFile(dataArray, size) {

	blobs = new Array();
    for (var i = 0; i < dataArray.size; i += size)
	{
		var copy = dataArray.slice();
		var partial = copy.slice(i, i+size);
		blobs.push(partial);
    }
	return blobs;
}

function uploadProcess(fileInputId)
{
	var file = document.getElementById(fileInputId).files[0]; 
	var reader = new FileReader();
	reader.readAsBinaryString(file);
	
	reader.onloadend  = function(evt)
	{
		var fr = evt.target.result;	
		fileUpload( fr );
	}
	
}

function fileUpload(inputDataArray)
{
	var since;
	var intervalid;
	var totalBytes = inputDataArray.length;
	var packets = new Array();
	
	var packetNum = 0;
	var packetCount = 0;
	var packetSize = 0;
	
	function startUpload()
	{
		intervalid = setInterval(function(){updateUploadStats();},1000);
		calculatePaketSize()
		createPackets();
		submitPacket();
	}	
	
	function calculatePaketSize()
	{
		var ideal_size = 3*1024*1024;
		var packet_count = Math.ceil( totalBytes/ideal_size);
		packetSize = Math.ceil(totalBytes/packet_count);
	}

	function createPackets()
	{	
		packets = splitFile(toBlob(inputDataArray), packetSize)
		packetCount = packets.length;
	}
	
	function updateUploadStats(e)
	{
		//displaying upload progress in GUI
	}
	
	function submitPacket()
	{
		xhr = new XMLHttpRequest();
		xhr.open("POST", 'index.php?controller=AdminVodVideo&action=VideoUpload&ajax=1&r='+packetNum+'&token='+token, true);
		xhr.setRequestHeader("Content-type","application/octet-stream");
		XMLHttpRequest.prototype.mySendAsBinary = function(text){
			this.send(text);
		}
		
		var eventSource = xhr.upload || xhr;
		
		eventSource.addEventListener("progress", function(e) {
			updateUploadStats(e);
		});
		
		xhr.onreadystatechange = function()
		{
			if(xhr.readyState == 4)
			{
				if(xhr.status == 200)
				{
					//server will return the string 'upload failed' if the file to be received was empty.
					
					if( xhr.responseText == 'upload failed')
					{
						console.log('FAILED , trying again in 3 s');
						setTimeout(submitPacket,3000);
					}
					else
					{
						updateUploadStats();
						packetNum++;
						if(packetNum == packetCount)
						{
							processOnServer();
						}
						else
						{
							submitPacket();
						}
					}
					

				}else{
					// process error
					console.log('we got a 500 error');	
				}
			}
		};
		since = Date.now();
		xhr.mySendAsBinary( packets[packetNum] );
	}
	
	function processOnServer()
	{
		//telling the server to piece the file back together.
	}
	
	startUpload();
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

0 个答案:

没有答案