第四篇:一文读懂前端上传下载(前端读取文件 | 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 的方法,保存文件到本地。

const loadFile = (fileName = "新建yaml文档.yaml", content) => { // 前端自动生成下载文件
  // content = reader.result 为文件的内容,也可以是修改后的内容。
  const aLink = document.createElement('a'); // 可以是任何能放置 url 的标签,比如 <img src=""/> <a href=""/>
  const blob = new Blob([content], { // content: 文件内容
    type: "" //type: file.type, 当值为空字符串时,下载的文件类型以文件名的尾缀为准。
  });
  aLink.download = fileName;
  aLink.href = URL.createObjectURL(blob);
  aLink.click();
  URL.revokeObjectURL(blob);
  aLink.remove();
}

 


 

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);

 

posted @ 2020-08-14 10:47  真的想不出来  阅读(1679)  评论(0编辑  收藏  举报