JS文件处理—读取本地文件(必须通过input控件才能实现) 及 下载文件

js 操作 文件的实现原理:

1、js是不能直接操作(读写)文件的,html的  input[type="file"] 控件是可以读取文件数据(获取文件数据流)的。js可以获取这个 input 标签的数据流,这样js就 可以操作 这个文件的数据流了,获取这个文件中数据了( js 还是不能 将数据写入文件中)。

   input[type="file"] 控件 操作文件,只能是用户主动 加载 文件到浏览器上。浏览器这种机制,确保了js无法 操作文件。只能在用户主动允许的情况下,将文件的数据流给 input控件。

2、input type="file"  控件文档:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/Input/file

3、js 获取 input中的文件流对象,里面只有几个属性(参考上面链接)。这个文件流数据是看不到,对这个文件流数据的操作,需要用对应的API接口,如下:

<input type="file" id="file"/>
    var input = document.querySelector('input');
    input.addEventListener('change', function() {
        console.log(this.files); // 我们是无法直接在 this.files 对象中获取到 数据流的,需要使用 FileReader 对象去 读取的。
    }, false);

  处理 不同格式的数据流,需要使用  对应读取数据流的 API(如,文本文件,使用readAsText去读取,获取对应的文本数据;图片文件,使用readAsDataURL去读取,获取对应文件的base64的数据格式)。

  a、读取 文本文件

    var input = document.querySelector('input');
    input.addEventListener('change', function() {
      if(this.files.length){
        let file = this.files[0];
        let reader = new FileReader();
        reader.onload = function(){
          console.log(this.result);  // 文件数据流,变成相应格式数据了。( 文本文件,就输出文本内的文本数据 )
        };
        reader.readAsText(file);
      }
    }, false);

  b、读取 图片文件

    var input = document.querySelector('input');
    input.addEventListener('change', function() {
      if(this.files.length){
        let file = this.files[0];
        let reader = new FileReader();
        reader.onload = function(){
          console.log(this.result);
        document.getElementById('preview').src = this.result;  // this.result 输入 图片的base64格式的数据
        };
        reader.readAsDataURL(file);
      }
    }, false);

4、FileReader 属性和方法:https://www.jianshu.com/p/cde728c4e334 

5、彻底弄懂文件和二进制数据的操作:https://blog.csdn.net/weixin_33807284/article/details/91420517

  a、Blob 对象:Blob对象代表了一段  二进制数据 。(通过这个对象,可以生成一个存在内存中的文本文件,通过a标签下载可以这个文件。如果要生成图片等非文本的文件,比较复杂,一般也不会这么用)

  b、FileList对象:<input type='file' multiple />标签 选择文件后的对象,这个对象指向 本地选中的文件。js是无法获取指向这个文件的url地址的(浏览器的安全机制)。

     说明:File 对象来自 FileList 对象,所以我把他们看成一类来对待。File 对象是特殊类型的 Blob。https://developer.mozilla.org/zh-CN/docs/Web/API/File

  c、URL对象:URL对象用于生成指向File对象或Blob对象的URL。(把内存中二进制数据,看成储存在内存中的一个文件。URL对象就是这个文件的路径)

  d、FileReader对象:FileReader API用于读取文件,即把文件内容读入内存。它的参数是File对象或Blob对象。(readAsText  返回文本字符串默认文本编码格式是’UTF-8’,可以通过可选的格式参数)

  个人总结:Blob 对象 和 FileList对象 都是二进制数据源。Blob 对象本身就是一个二进制数据;而FileList对象是指向一个二进制文件,可以获取到这个文件的二进制数据。

         而 URL对象 和 FileReader对象 都是操作这两个 二进制数据源的 API。(FileList对象和Blob对象一样使用,因为FileList对象会隐式转化为 Blob对象)

    <input type="file" id="file"/>
     // URL 对象 对Blob 和 FileList 二进制数据源 操作
        let blob = new Blob(["Hello World"],{ "type" : "text\/xml" }); // 本身就是二进制数据
        let input = document.querySelector('input');  // 选择文件后,才有 FileList 对象。所以对input选中文件的操作,应该是input控件 change事件后。

        console.log(URL.createObjectURL(blob));   //  blob:null/16e3804c-452f-408b-b514-bbe27a874837

        input.addEventListener('change', function() {
            if(this.files.length){
                let file = this.files[0];
                console.log(URL.createObjectURL(file)); //  blob:null/88cca1d4-442c-4ac9-a7fd-402b75990d50
            }
        }, false);
    // FileReader 对象对Blob 和 FileList 二进制数据源 操作
        let readerBlob = new FileReader();
        readerBlob.onload = function(){
            console.log(this.result);  // Hello World
        };
        readerBlob.readAsText(blob);

        input.addEventListener('change', function() {
            if(this.files.length){
                let file = this.files[0];
                let reader = new FileReader();
                reader.onload = function(){
                console.log('dd',this.result); // happy new 【这个是文本文件中的文字
                };
                reader.readAsText(file);
            }
        }, false);    

 

6、

个人理解:input[type="file"] 控件,选中文件后,这个控件对象就指向这个本地文件,在需要使用这个文件时,通过相应的 API(如,FileReader 对象) 把这个对象指向的文件,读取到内存中(以二进制数据存在)。


 js 操作文件 实践

一、 ajax传递文件

1、H5 FormData对象的使用——进行Ajax请求并上传文件   :    https://www.cnblogs.com/lyr1213/p/6238026.html

2、js发送post请求下载文件:ajax是不能直接下载文件的,所以使用js进行post请求需要借助标签实现。  http://www.cnblogs.com/xiexingen/p/4560547.html 或 https://www.cnblogs.com/micro-chen/p/5367550.html 或 https://www.jianshu.com/p/6a9947cc3849(推荐)

 

二、 js通过CSV导入excel数据:https://segmentfault.com/a/1190000015080835?utm_source=tag-newest

   说明:不同格式的文件,他们的本质都是二进制数据。不同 格式的文件,只是数据格式不同,针对不同的文件,使用相应的解码格式就可以获取需要的数据。

 

三、用户选中本地的图片,并显示这个图片。 https://segmentfault.com/a/1190000018314505

 

 


 前端下载excel文件功能的三种方法https://www.cnblogs.com/houxiaohang/p/6846467.html

前端下载文件:

一、请求的文件url,不需要 给请求头或请求体添加信息,设置认证信息(如,请求头 添加 token值)。这种下载链接直接在浏览器地址上输入地址就可以下载,或打开。

  这种请求,有 3种方式下载:

  1、a 标签下载,正规下载方式。a标签上可以设置下载的文件 文件名。(一般都是这种方式下载文件)

  2、location.href = downloadUrl 。这种方式下载只能是浏览器不能识别的文件。不然无法下载,而且下载的文件不能命名。

  3、window.open(downloadUrl) 。 这种方式和 第二种 是一样的,只是这种方式是打开一个新的窗口跳转到下载链接,而第二种是在当前窗口跳转到下载链接。

这种请求 通过 a标签,设置down属性 就可以下载。  

二、请求的文件url,需要权限控制(不管是get还是post请求都一样),这种文件的下载只能通过js的ajax请求实现。直接在浏览器上输入文件请求地址,下载不了。(后管平台中展示的数据 常常需要导出excel文件,就是这种请求)

  参考:https://www.cnblogs.com/roseAT/p/11074765.html  或  https://blog.csdn.net/aydongzhiping/article/details/82462473

  1、因为 请求有权限,需要在请求上添加认证信息(如,请求头上添加token值),只有ajax请求可以给请求头添加信息。

  2、ajax请求文件,请求回来的数据是一个二进制数据。这个请求很简单,难点是把二进制数据下载下来。这里关键是用到了 window.URL 这个API。

  3、URL对象用于生成指向File对象或Blob对象的URL。通过这个API可以生成一个指向  内存中二进制数据(ajax请求回来的数据 )的url地址。这时,内存中的二进制数据就可以 和 普通文件那样下载了。

const requestFile = url => {
  const xhr = new XMLHttpRequest();
  // GET请求,请求路径url,async(是否异步)
  xhr.open('GET', url, true);
  // 设置请求头参数的方式,如果没有可忽略此行代码
  xhr.setRequestHeader(AUTHORIZATION_REQUEST_HEADER, 'Token值');
  // 设置响应类型为 blob
  xhr.responseType = 'blob';
  // 关键部分
  xhr.onload = function (e) {
    // 如果请求执行成功
    if (this.status === 200) {
      const disposition = xhr.getResponseHeader('Content-disposition');
      // 从响应头content-disposition字符串(类似这种格式attachment;filename=2022011340798353+%287%29+%281%29.pdf)取出文件名
      const fileName = disposition.split(";")[1].split("filename=")[1]  // 一般content-disposition 都是这种结构,如果结构出现 不一致,那肯定要另外考虑了
      const a = document.createElement('a');
      // 创键临时url对象
      const downloadUrl = URL.createObjectURL(this.response);

      a.href = downloadUrl;  // 这里也可以使用location.href 或 window.open()进行下载,但是这两个不能给文件命名。
      a.download = decodeURI(filename);
      a.click();
      // 释放之前创建的URL对象
      window.URL.revokeObjectURL(downloadUrl);
    }
  };
  // 发送请求
  xhr.send();
}

  注意:数据的 响应类型很重要,不然返回的数据,xhr对象无法正确处理返回的数据。默认的响应类型 text 类型 ,下载时,响应类型 必须设置 为 blob

       【亲测,用axios插件】没有设置 这个 responseType 的响应类型,xhr 处理后给出的 是字符串数据;设置 响应类型 为 blob,xhr 处理后给出的 是 blob 对象的数据。

 

总结:不同的DOM有不同的默认事件行为,一般是在点击事件时触发(如,a标签的下载行为,input-file控件打开文件系统)。js是没有这种行为的,js要实现这种行为就必须借助相应的标签。通过js触发这个标签的事件,执行相应的默认行为。


聊聊JS的二进制家族:BlobArrayBufferBufferhttps://www.cnblogs.com/penghuwan/p/12053775.html

1、Blob:Blob是针对文件的,或者可以说它就是一个文件对象,同时呢我们发现Blob欠缺对二进制数据的细节操作能力,比如如果如果要具体修改某一部分的二进制数据,Blob显然就不够用了,而这种细粒度的功能则可以由下面介绍的ArrayBuffer来完成。

2、ArrayBuffer:前端的一个通用的二进制缓冲区,类似数组,但在API和特性上却有诸多不同。

3、Buffer:Node.js提供的一个二进制缓冲区,常用来处理I/O操作 。Buffer是Node.js提供的对象,前端没有。

 

posted @ 2018-06-06 12:51  吴飞ff  阅读(11592)  评论(0编辑  收藏  举报