第四篇:一文读懂前端上传下载(前端读取文件 | FileReader 对象 | 前端保存文件到本地 | Blob 对象 | URL 对象)
这篇文章是这个分类下的第四篇随笔了,之前可能对文件上传还不是很清晰,写到这篇,也就明白套路了。
ps:这就是写博客的好处。
前端读取文件
第一步:定义一个input标签type="file"
觉得 <input/> 样式难看又难改的,请看一下这个分类下的第三篇随笔。
如果需要对读取到的文本内容进行修改,可以用 <textarea></textarea> 多行文本域,简单模拟一个前端代码编辑器。推荐使用 codemirror2(代码编辑器)
<input type="file" onChange={(ev) => getFiles(ev.target.files)} accept=".yaml" // 规定可以读取的文件类型(不写或等于""时,为全部类型。可以连写->".xlsx, .txt, .yaml") // multiple="multiple" // 可以接受多个值得上传 字段 /> <span id="textInner" > // 留一个元素,可以将获取到的文件信息展示出来,注意不要忘了设置该元素的样式(宽、高、、、) </span>
第二步:定义一个 getFiles 的方法,读取上传的文件。
getFiles = (files) => { const textInner = document.getElementById("textInner"); // 获取一个标签,把读取的内容插进去 if (files.length) { const file = files[0]; const reader = new FileReader(); // new一个FileReader实例 if (/text+/.test(file.type)) { // 判断文件类型,是不是text类型 reader.readAsText(file); reader.onload = function () { textInner.innerText = this.result } } else if (/image+/.test(file.type)) { // 判断文件是不是imgage类型 reader.readAsDataURL(file); reader.onload = function () { textInner.innerHTML = '<img src="' + this.result + '"/>' } } else { // 其它类型 reader.readAsText(file); reader.onload = function () { // this === reader 非箭头函数,谁调用this指向谁 console.log(this.result) // 文件内容 } } } }
到这里,读取文件就结束了,下面来了解一下 html5 的 FileReader 对象及其属性
FileReader 对象
FileReader提供了如下方法:
/* reader.readAsText(file, [encoding]); // 将文件读取为文本,其中第二个参数是文本的编码方式,不写默认值为 UTF-8 reader.readAsDataURL(file); // 读取文件内容,结果用data:url的字符串形式表示(常用于媒体文件:图片、音频、视频) reader.readAsArrayBuffer(file); // 按字节读取文件内容,结果用ArrayBuffer对象表示 reader.readAsBinaryString(file); // 按字节读取文件内容,结果为文件的二进制串 reader.abort() // 终止读取文件 */
FileReader事件:
/* onabort 当读取操作被终止时调用 onerror 当读取操作发生错误时调用 onload 当读取操作成功完成时调用 onloadend 当读取操作完成时调用,无论成功失败 onloadstart 当读取操作开始时调用 onprogress 当读取数据过程中周期性调用 */
文件一旦开始读取,无论成功或失败,实例的 result 属性都会被填充。如果读取失败,则 result 的值为 null ,否则即是读取的结果。
如果读取文件过大的话fileReader允许分段读取文件;
var blob_file; if(file.webkitSlice) { //chrome blob_file= file.webkitSlice(start, end + 1, 'text/plain;charset=UTF-8'); } else if(file.mozSlice) { //Firefox blob_file= file.mozSlice(start, end + 1, 'text/plain;charset=UTF-8'); }
顺便唠叨一下base64编码的优缺点:
优点:
1.减少了http请求。
2.没有跨域的问题。
3.直接放在路径里不需要清理缓存。
缺点:
1.IE6/7不支持(不过这个问题不大);
2.base64本质上是将图片以二进制的字母展示,字符量过大无形中增加了css/html文件的大小;
前端文件到本地
第一步:随便来个元素,绑定点击事件
<button onClick={() => loadFile(file.name, value)}>保存到本地</button>
第二步:定义一个 loadFile 的方法,保存文件到本地。
Blob 对象
概念:
Blob(Binary Large Object)对象代表了一段二进制数据,提供了一系列操作接口。其他操作二进制数据的 API(比如 File 对象),都是建立在 Blob 对象基础上的,继承了它的属性和方法。
两种使用方式:
生成 Blob 对象有两种方法:一种是使用 Blob 构造函数,另一种是对现有的 Blob 对象使用 slice 方法切出一部分。
(1)Blob 构造函数,接受两个参数。第一个参数是一个包含实际数据的数组,第二个参数是数据的类型,这两个参数都不是必需的。
var a = ["hello", "world"]; var myBlob = new Blob(a, { "type" : "text/xml" }); console.log(myBlob);
(2)Blob 对象的 slice 方法,将二进制数据按照字节分块,返回一个新的 Blob 对象。
var a = ["hello", "world"]; var myBlob = new Blob(a, { "type" : "text/xml" }); var newBlob = myBlob.slice(0, 5); console.log(newBlob);
Blob 对象有两个只读属性:
size:二进制数据的大小,单位为字节。(文件上传时可以在前端判断文件大小是否合适)
type:二进制数据的 MIME 类型,全部为小写,如果类型未知,则该值为空字符串。(文件上传时可以在前端判断文件类型是否合适)
URL 对象
调用 URL 对象的 createObjectURL 方法,传入一个 File 对象或者 Blob 对象,能生成一个链接,听起来好像很吊的样子。
var objecturl = window.URL.createObjectURL(blob);
上面的代码会对二进制数据生成一个 URL,这个 URL 可以放置于任何通常可以放置 URL 的地方,比如 img 标签的 src 属性。需要注意的是,即使是同样的二进制数据,每调用一次 URL.createObjectURL 方法,就会得到一个不一样的 URL。
这个 URL 的存在时间,等同于网页的存在时间,一旦网页刷新或卸载,这个 URL 就失效。(File 和 Blob 又何尝不是这样呢)除此之外,也可以手动调用 URL.revokeObjectURL 方法,使 URL 失效。
window.URL.revokeObjectURL(objectURL); var blob = new Blob(["Hello hanzichi"]); var a = document.createElement("a"); a.href = window.URL.createObjectURL(blob); a.download = "a.txt"; a.textContent = "Download"; document.body.appendChild(a);