Home >Web Front-end >H5 Tutorial >Case study of file domain + FileReader in html5 reading files in sections and uploading to server
1. Simply read the file into Blobs in segments and upload it to the server with ajax
<p class="container"> <p class="panel panel-default"> <p class="panel-heading">分段读取文件:</p> <p class="panel-body"> <input type="file" id="file" /> <blockquote style="word-break:break-all;"></blockquote> </p> </p> </p>
JS:
/* * 分段读取文件为blob ,并使用ajax上传到服务器 * 分段上传exe文件会抛出异常 */ var fileBox = document.getElementById('file'); file.onchange = function () { //获取文件对象 var file = this.files[0]; var reader = new FileReader(); var step = 1024 * 1024; var total = file.size; var cuLoaded = 0; console.info("文件大小:" + file.size); var startTime = new Date(); //读取一段成功 reader.onload = function (e) { //处理读取的结果 var loaded = e.loaded; //将分段数据上传到服务器 uploadFile(reader.result, cuLoaded, function () { console.info('loaded:' + cuLoaded + 'current:' + loaded); //如果没有读完,继续 cuLoaded += loaded; if (cuLoaded < total) { readBlob(cuLoaded); } else { console.log('总共用时:' + (new Date().getTime() - startTime.getTime()) / 1000); cuLoaded = total; } }); } //指定开始位置,分块读取文件 function readBlob(start) { //指定开始位置和结束位置读取文件 //console.info('start:' + start); var blob = file.slice(start, start + step); reader.readAsArrayBuffer(blob); } //开始读取 readBlob(0); //关键代码上传到服务器 function uploadFile(result, startIndex, onSuccess) { var blob = new Blob([result]); //提交到服务器 var fd = new FormData(); fd.append('file', blob); fd.append('filename', file.name); fd.append('loaded', startIndex); var xhr = new XMLHttpRequest(); xhr.open('post', '../ashx/upload2.ashx', true); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { // var data = eval('(' + xhr.responseText + ')'); console.info(xhr.responseText); if (onSuccess) onSuccess(); } } //开始发送 xhr.send(fd); } }
Backend code:
/// <summary> /// upload2 的摘要说明 /// </summary> public class upload2 : IHttpHandler { LogHelper.LogHelper _log = new LogHelper.LogHelper(); int totalCount = 0; public void ProcessRequest(HttpContext context) { HttpContext _Context = context; //接收文件 HttpRequest req = _Context.Request; if (req.Files.Count <= 0) { WriteStr("获取服务器上传文件失败"); return; } HttpPostedFile _file = req.Files[0]; //获取参数 // string ext = req.Form["extention"]; string filename = req.Form["filename"]; //如果是int 类型当文件大的时候会出问题 最大也就是 1.9999999990686774G int loaded = Convert.ToInt32(req.Form["loaded"]); totalCount += loaded; string newname = @"F:\JavaScript_Solution\H5Solition\H5Solition\Content\TempFile\"; newname += filename; //接收二级制数据并保存 Stream stream = _file.InputStream; if (stream.Length <= 0) throw new Exception("接收的数据不能为空"); byte[] dataOne = new byte[stream.Length]; stream.Read(dataOne, 0, dataOne.Length); FileStream fs = new FileStream(newname, FileMode.Append, FileAccess.Write, FileShare.Read, 1024); try { fs.Write(dataOne, 0, dataOne.Length); } finally { fs.Close(); stream.Close(); } _log.WriteLine((totalCount + dataOne.Length).ToString()); WriteStr("分段数据保存成功"); } private void WriteStr(string str) { HttpContext.Current.Response.Write(str); } public bool IsReusable { get { return true; } }
2. Read the file in sections as blobs, upload them to the server using ajax, and add stop and continue functions.
<p class="container"> <p class="panel panel-default"> <p class="panel-heading">分段读取文件:</p> <p class="panel-body"> <input type="file" id="file" /> <br /> <input type="button" value="中止" onclick="stop();" />  <input type="button" value="继续" onclick="containue();" /> <br /> <progress id="progressOne" max="100" value="0" style="width:400px;"></progress> <blockquote id="Status" style="word-break:break-all;"></blockquote> </p> </p> </p>
JS:
/* * 分段读取文件为blob ,并使用ajax上传到服务器 * 使用Ajax方式提交上传数据文件大小应该有限值,最好500MB以内 * 原因短时间过多的ajax请求,Asp.Net后台会崩溃获取上传的分块数据为空 * 取代方式,长连接或WebSocket */ var fileBox = document.getElementById('file'); var reader = null; //读取操作对象 var step = 1024 * 1024 * 3.5; //每次读取文件大小 var cuLoaded = 0; //当前已经读取总数 var file = null; //当前读取的文件对象 var enableRead = true;//标识是否可以读取文件 fileBox.onchange = function () { //获取文件对象 file = this.files[0]; var total = file.size; console.info("文件大小:" + file.size); var startTime = new Date(); reader = new FileReader(); //读取一段成功 reader.onload = function (e) { //处理读取的结果 var result = reader.result; var loaded = e.loaded; if (enableRead == false) return false; //将分段数据上传到服务器 uploadFile(result, cuLoaded, function () { console.info('loaded:' + cuLoaded + '----current:' + loaded); //如果没有读完,继续 cuLoaded += loaded; if (cuLoaded < total) { readBlob(cuLoaded); } else { console.log('总共用时:' + (new Date().getTime() - startTime.getTime()) / 1000); cuLoaded = total; } //显示结果进度 var percent = (cuLoaded / total) * 100; document.getElementById('Status').innerText = percent; document.getElementById('progressOne').value = percent; }); } //开始读取 readBlob(0); //关键代码上传到服务器 function uploadFile(result, startIndex, onSuccess) { var blob = new Blob([result]); //提交到服务器 var fd = new FormData(); fd.append('file', blob); fd.append('filename', file.name); fd.append('loaded', startIndex); var xhr = new XMLHttpRequest(); xhr.open('post', '../ashx/upload2.ashx', true); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { if (onSuccess) onSuccess(); } else if (xhr.status == 500) { //console.info('请求出错,' + xhr.responseText); setTimeout(function () { containue(); }, 1000); } } //开始发送 xhr.send(fd); } } //指定开始位置,分块读取文件 function readBlob(start) { //指定开始位置和结束位置读取文件 var blob = file.slice(start, start + step); reader.readAsArrayBuffer(blob); } //中止 function stop() { //中止读取操作 console.info('中止,cuLoaded:' + cuLoaded); enableRead = false; reader.abort(); } //继续 function containue() { console.info('继续,cuLoaded:' + cuLoaded); enableRead = true; readBlob(cuLoaded); }
Backend code is the same as above
3. Read the file in segments It is a binary array and is uploaded to the server using ajax
Using binary array transmission is very inefficient, and the final file deviates somewhat from the original size
HTML content is the same as above
JS:
/* * 分段读取文件为二进制数组 ,并使用ajax上传到服务器 * 使用二进制数组传递的方式,效率特别低,最终文件还与原始大小有些偏差 */ var fileBox = document.getElementById('file'); var reader = new FileReader(); //读取操作对象 var step = 1024 * 1024; //每次读取文件大小 var cuLoaded = 0; //当前已经读取总数 var file = null; //当前读取的文件对象 var enableRead = true;//标识是否可以读取文件 fileBox.onchange = function () { //获取文件对象 if (file == null) //如果赋值多次会有丢失数据的可能 file = this.files[0]; var total = file.size; console.info("文件大小:" + file.size); var startTime = new Date(); //读取一段成功 reader.onload = function (e) { //处理读取的结果 var result = reader.result; var loaded = e.loaded; if (enableRead == false) return false; //将分段数据上传到服务器 uploadFile(result, cuLoaded, function () { console.info('loaded:' + cuLoaded + '----current:' + loaded); //如果没有读完,继续 cuLoaded += loaded; if (cuLoaded < total) { readBlob(cuLoaded); } else { console.log('总共用时:' + (new Date().getTime() - startTime.getTime()) / 1000); cuLoaded = total; } //显示结果进度 var percent = (cuLoaded / total) * 100; document.getElementById('Status').innerText = percent; document.getElementById('progressOne').value = percent; }); } //开始读取 readBlob(0); //关键代码上传到服务器 function uploadFile(result, startIndex, onSuccess) { var array = new Int8Array(result); console.info(array.byteLength); //提交到服务器 var fd = new FormData(); fd.append('file', array); fd.append('filename', file.name); fd.append('loaded', startIndex); var xhr = new XMLHttpRequest(); xhr.open('post', '../ashx/upload3.ashx', true); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { // console.info(xhr.responseText); if (onSuccess) onSuccess(); } else if (xhr.status == 500) { console.info('服务器出错'); reader.abort(); } } //开始发送 xhr.send(fd); } } //指定开始位置,分块读取文件 function readBlob(start) { //指定开始位置和结束位置读取文件 var blob = file.slice(start, start + step); reader.readAsArrayBuffer(blob); } //中止 function stop() { //中止读取操作 console.info('中止,cuLoaded:' + cuLoaded); enableRead = false; reader.abort(); } //继续 function containue() { console.info('继续,cuLoaded:' + cuLoaded); enableRead = true; readBlob(cuLoaded); }
Backend code:
/// <summary> /// upload3 的摘要说明 /// </summary> public class upload3 : IHttpHandler { LogHelper.LogHelper _log = new LogHelper.LogHelper(); int totalCount = 0; public void ProcessRequest(HttpContext context) { HttpContext _Context = context; //接收文件 HttpRequest req = _Context.Request; string data = req.Form["file"]; //转换方式一 //int[] intData = data.Split(',').Select(q => Convert.ToInt32(q)).ToArray(); //byte[] dataArray = intData.ToList().ConvertAll(x=>(byte)x).ToArray(); //转换方式二 byte[] dataArray = data.Split(',').Select(q => int.Parse(q)).Select(q => (byte)q).ToArray(); //获取参数 string filename = req.Form["filename"]; //如果是int 类型当文件大的时候会出问题 最大也就是 1.9999999990686774G int loaded = Convert.ToInt32(req.Form["loaded"]); totalCount += loaded; string newname = @"F:\JavaScript_Solution\H5Solition\H5Solition\Content\TempFile\"; newname += filename; try { // 接收二级制数据并保存 byte[] dataOne = dataArray; FileStream fs = new FileStream(newname, FileMode.Append, FileAccess.Write, FileShare.Read, 1024); try { fs.Write(dataOne, 0, dataOne.Length); } finally { fs.Close(); } _log.WriteLine((totalCount + dataOne.Length).ToString()); WriteStr("分段数据保存成功"); } catch (Exception ex) { throw ex; } } private void WriteStr(string str) { HttpContext.Current.Response.Write(str); } public bool IsReusable { get { return false; } } }
Description: Use Ajax to upload, the file cannot be too large. It is better to be less than three to four hundred megabytes, because too many continuous Ajax requests will cause the background to crash, and the data in the InputStream will be empty, especially during the Google browser test.
The above is the detailed content of Case study of file domain + FileReader in html5 reading files in sections and uploading to server. For more information, please follow other related articles on the PHP Chinese website!