哈喽!你好今天就来教你如何用FileReader修复H5里的文件并顺利传到服务器~看起来可能有些难度,别担心,我尽量说简单点给你听哈。做网站,难免要上传文件。特别是大文件,直接传上去服务器搞不好就崩溃了。所以说,了解分段上传简直太重要!
为什么需要分段上传
啥叫分段上传?简单说,比如要传个大几百兆的文件,一股脑儿全传很可能因为网络或服务器负荷过大搞不定。这时候就得“化整为零”,就像吃大蛋糕,一小块一小块地来,这样不仅不慢吞吞,还不怕搞坏肚子!
分段上,失败了也没事,就改那出错的部分就行。不用整个重新弄,省时省力,还能节省点儿网络流量!
FileReader的基本使用
HTML5给了咱们个超给力的FileReader,想读啥就看它心情(readAsText、readAsBinaryString或readAsArrayBuffer)。不过,搞懂了这个readAsArrayBuffer就啥都不怕了哦~
其实用FileReader读文件很容易!先搞出个叫FileReader的小伙伴,接着就能用readAsArrayBuffer来拉取文件内容。完了之后,FileReader还会搞定一个叫做onload的事,这下子你就可以瞅瞅刚读取到的记儿了!
分段读取文件的实现
分段读取文件:
教你看文件那部分!你会用File吗?里面有个Slice功能,就跟我们切豆腐似的,找到开头尾部,搞清啥类型的数据,然后就能简单剪裁了!找准起点终点,这个超简单!
搞定文档后,用FileReader一个个读出来,然后就把这些上传到服务器上!不过记得,传的东西别太大,要不然可能会出问题的。
Ajax上传的注意事项
使用AJAX上传大文件得注意!首先,尽量控制在300M以内,否则后台可能会挂掉哦;再来说说,特别是用Google Chrome时,输入流有时候会啥都得不到。
哎呦,得想想万一上传过程中断网怎么办?得加个功能才行,这样就算没网也能继续传,不用重新开始。这新功能就等于帮你记着已经上传好的那部分内容,下次网好了就能从那儿顺利接上!
实战案例:简单分段读取文件为Blob,Ajax上传到服务器
你别以为做前端就是搞搞cs s、html、js那么容易,后面还等着你解决其他大问题!
前端JS代码:
javascript/* * 分段读取文件为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); } }// 创建一个FileReader对象
读卡器做好了,现在就用它!
// 读取文件的某一段
就是用了个有趣的function,file.slice(start, end),把reader变成了数组buffer~
// 读取完成后上传
reader.onload = function(e) {
搞了个名叫Blob的玩意儿,专门放eventTarget收敛过来的数据。
// 使用Ajax上传blob////// upload2 的摘要说明 /// 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_SolutionH5SolitionH5SolitionContentTempFile"; 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; } }我们搞个新对象叫xhr,它是XMLHttpRequest。
想要上传文件,就得使个XHR(也就是xmlhttp哦)给'/upload'发个"POST"请求。记住勾选那个“异步加载模式”,事儿就成了!
xhr.send(blob);
};后台代码:
“`java
// 接收上传的文件段
@PostMapping(“/upload”)
分段读取文件:
你知道怎么用这个方法传文件吗?只需要一个叫做`file`MultiPartFile的参数,超容易的!
// 处理接收到的文件段
}
实战案例:分段读取文件为Blob,并添加中止、继续功能
这儿就教你个新鲜玩意儿,能让大文件变得小一些。其实就是网页前端的Java脚本跟服务端啰嗦事儿,不难!
// 添加中止功能
xhr.onabort = function() {
// 处理中止事件
};
/* * 分段读取文件为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); }// 添加继续功能
xhr.onload = function() {
// 处理上传完成事件
后台代码与上一个案例相同。
总结
看了那个例子,你现在应该知道怎么用FileReader把文件拆分?然后和Ajax一拍即合,直接搞定大文件传输问题,速度还挺快。这下子,上传巨型文件的烦恼可以说拜拜了!
聊聊天,说下大家传文件时遇见过什么困扰呗,也让咱们了解一下。
原文链接:https://www.icz.com/technicalinformation/web/2024/07/19983.html,转载请注明出处~~~
评论0