zoukankan      html  css  js  c++  java
  • 文件和二进制数据的操作

    ----------------------------------------------------------------------------------------------------------

    文件和二进制数据的操作

    历史上,JavaScript无法处理二进制数据

    (  文本文件和二进制文件的区别?  文本文件和二进制文件并无本质的差别,他们的区别在于打开这个文件的程序在对其内容的解释上,我们可以把一个典型的所谓二进制文件(bmp)当作文本文件来打开,是同样可以的,只是得到的内容就是一些乱七八糟的符号了。反过来,也是同样成立)

    如果一定要处理的话,只能使用charCodeAt()方法,一个个字节地从文字编码转成二进制数据,还有一种办法是将二进制数据转成Base64编码,再进行处理。这两种方法不仅速度慢,而且容易出错。

    ECMAScript 5引入了Blob对象,允许直接操作二进制数据。

    Blob对象是一个代表二进制数据的基本对象,在它的基础上,又衍生出一系列相关的API,用来操作文件。

    • File对象:负责处理那些以文件形式存在的二进制数据也就是操作本地文件;
    • FileList对象:File对象的网页表单接口;
    • FileReader对象:负责将二进制数据读入内存内容;
    • URL对象:用于对二进制数据生成URL。

    Blob对象

    Blob(Binary Large Object)对象代表了一段二进制数据,提供了一系列操作接口。其他操作二进制数据的API(比如File对象),都是建立在Blob对象基础上的,继承了它的属性和方法。

    生成Blob对象有两种方法

    1. 一种是使用Blob构造函数,
    2. 另一种是对现有的Blob对象使用slice方法切出一部分。

    (1)Blob构造函数,接受两个参数。第一个参数是一个包含实际数据的数组,第二个参数是数据的类型,这两个参数都不是必需的。

    var htmlParts = ["<a id="a"><b id="b">hey!</b></a>"];
    var myBlob = new Blob(htmlParts, { "type" : "text/xml" });
    

    下面是一个利用Blob对象,生成可下载文件的例子。

    var blob = new Blob(["Hello World"]);
    var body = documment.getElementsByTagName("body")[0];
    var a = document.createElement("a");
    a.href = window.URL.createObjectURL(blob);
    a.download = "hello-world.txt";
    a.textContent = "Download Hello World!";
    
    body.appendChild(a);
    

    上面的代码生成了一个超级链接,点击后提示下载文本文件hello-world.txt,文件内容为“Hello World”。

    (2)Blob对象的slice方法,将二进制数据按照字节分块,返回一个新的Blob对象。

    var newBlob = oldBlob.slice(startingByte, endindByte);
    

    下面是一个使用XMLHttpRequest对象,将大文件分割上传的例子。

    function upload(blobOrFile) {
      var xhr = new XMLHttpRequest();
      xhr.open('POST', '/server', true);
      xhr.onload = function(e) { ... };
      xhr.send(blobOrFile);
    }
    
    document.querySelector('input[type="file"]').addEventListener('change', function(e) {
      var blob = this.files[0];
    
      const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes.
      const SIZE = blob.size;
    
      var start = 0;
      var end = BYTES_PER_CHUNK;
    
      while(start < SIZE) {
        upload(blob.slice(start, end));
    
        start = end;
        end = start + BYTES_PER_CHUNK;
      }
    }, false);
    
    })()

    (3)Blob对象有两个只读属性

    • size:二进制数据的大小,单位为字节。
    • type:二进制数据的MIME类型,全部为小写,如果类型未知,则该值为空字符串。

    在Ajax操作中,如果xhr.responseType设为blob,接收的就是二进制数据。

    FileList对象

    FileList对象针对表单的file控件。当用户通过file控件选取文件后,这个控件的files属性值就是FileList对象。它在结构上类似于数组,包含用户选取的多个文件。

    <input type="file" id="input" onchange="console.log(this.files.length)" multiple />
    

    当用户选取文件后,就可以读取该文件。

    var selected_file = document.getElementById('input').files[0];
    

    采用拖放方式,也可以得到FileList对象。

    var dropZone = document.getElementById('drop_zone');
    dropZone.addEventListener('drop', handleFileSelect, false);
    
    function handleFileSelect(evt) {
        evt.stopPropagation();
        evt.preventDefault();
    
        var files = evt.dataTransfer.files; // FileList object.
    
        // ...
    }
    

    上面代码的 handleFileSelect 是拖放事件的回调函数,它的参数evt是一个事件对象,该参数的dataTransfer.files属性就是一个FileList对象,里面包含了拖放的文件。

    File API

    File API提供File对象,它是FileList对象的成员,包含了文件的一些元信息,比如文件名、上次改动时间、文件大小和文件类型。

    var selected_file = document.getElementById('input').files[0];
    
    var fileName = selected_file.name;
    var fileSize = selected_file.size;
    var fileType = selected_file.type;
    

    File对象的属性值如下。

    • name:文件名,该属性只读。
    • size:文件大小,单位为字节,该属性只读。
    • type:文件的MIME类型,如果分辨不出类型,则为空字符串,该属性只读。
    • lastModified:文件的上次修改时间,格式为时间戳。
    • lastModifiedDate:文件的上次修改时间,格式为Date对象实例。
    $('#upload-file').files[0]
    // {
    //   lastModified: 1449370355682,
    //   lastModifiedDate: Sun Dec 06 2015 10:52:35 GMT+0800 (CST),
    //   name: "HTTP 2 is here Goodbye SPDY Not quite yet.png",
    //   size: 17044,
    //   type: "image/png"
    // }

    FileReader对象

    FileReader

    FileReader is used to read the contents of a Blob or File.(FileReader是用来读取Blob或File对象的内容的)

    FileReader对象用于读取文件,即把文件内容读入内存。它的参数是File对象或Blob对象。

    对于不同类型的文件,FileReader使用不同的方法读取。

    • readAsBinaryString(Blob|File):返回二进制字符串,该字符串每个字节包含一个0到255之间的整数。

    • readAsText(Blob|File, opt_encoding) :返回文本字符串。默认情况下,文本编码格式是'UTF-8',可以通过可选的格式参数,指定其他编码格式的文本。

    • readAsDataURL(Blob|File):返回一个基于Base64编码的data-uri对象。

    • readAsArrayBuffer(Blob|File) :返回一个ArrayBuffer对象。

    readAsText方法用于读取文本文件,它的第一个参数是File或Blob对象,第二个参数是前一个参数的编码方法,如果省略就默认为UTF-8编码。该方法是异步方法,一般监听onload事件,用来确定文件是否加载结束,方法是判断FileReader实例的result属性是否有值。其他三种读取方法,用法与readAsText方法类似。

    var reader = new FileReader();
    
    reader.onload = function(e) {
      var text = reader.result;
    }
    
    reader.readAsText(file, encoding);
    

    readAsDataURL方法返回一个data URL,它的作用基本上是将文件数据进行Base64编码。你可以将返回值设为图像的src属性。

    var reader = new FileReader();
    
    reader.onload = function(e) {
      var dataURL = reader.result;
    }
    
    reader.readAsDataURL(file);
    

    readAsBinaryString方法可以读取任意类型的文件,而不仅仅是文本文件,返回文件的原始的二进制内容。这个方法与XMLHttpRequest.sendAsBinary方法结合使用,就可以使用JavaScript上传任意文件到服务器。

    var reader = new FileReader();
    
    reader.onload = function(e) {
      var rawData = reader.result;
    }
    
    reader.readAsBinaryString(file);
    

    readAsArrayBuffer方法读取文件,返回一个类型化数组(ArrayBuffer),即固定长度的二进制缓存数据。在文件操作时(比如将JPEG图像转为PNG图像),这个方法非常方便。

    var reader = new FileReader();
    
    reader.onload = function(e) {
      var arrayBuffer = reader.result;
    }
    
    reader.readAsArrayBuffer(file);
    

    除了以上四种不同的读取文件方法,FileReader对象还有一个abort方法,用于中止文件上传。

    var reader = new FileReader();
    
    reader.abort();

    FileReader对象采用异步方式读取文件,可以为一系列事件指定回调函数。

    • onabort方法:读取中断或调用reader.abort()方法时触发。
    • onerror方法:读取出错时触发。
    • onload方法:读取成功后触发。
    • onloadend方法:读取完成后触发,不管是否成功。触发顺序排在 onload 或 onerror 后面。
    • onloadstart方法:读取将要开始时触发。
    • onprogress方法:读取过程中周期性触发。

    下面的代码是如何展示文本文件的内容。

    var reader = new FileReader();
    
    reader.onload = function(e){
      console.log(e.target.result);
    }
    
    reader.readAsText(blob);

    onload事件的回调函数接受一个事件对象,该对象的target.result就是文件的内容。

    下面是一个使用readAsDataURL方法,为img元素添加src属性的例子。

    var reader = new FileReader();
    
    reader.onload = function(e) {
        document.createElement('img').src = e.target.result;
    
    };
    
    reader.readAsDataURL(f);

    下面是一个onerror事件回调函数的例子。

    var reader = new FileReader();
    reader.onerror = errorHandler;
    
    function errorHandler(evt) {
      switch(evt.target.error.code) {
        case evt.target.error.NOT_FOUND_ERR:
          alert('File Not Found!');
          break;
        case evt.target.error.NOT_READABLE_ERR:
          alert('File is not readable');
          break;
        case evt.target.error.ABORT_ERR:
          break;
        default:
          alert('An error occurred reading this file.');
      };
    }

    下面是一个onprogress事件回调函数的例子,主要用来显示读取进度。

    var reader = new FileReader();
    reader.onprogress = updateProgress;
    
    function updateProgress(evt) {
      if (evt.lengthComputable) {
        var percentLoaded = Math.round((evt.loaded / evt.totalEric Bidelman) * 100);
          
        var progress = document.querySelector('.percent');
        if (percentLoaded < 100) {
          progress.style.width = percentLoaded + '%';
          progress.textContent = percentLoaded + '%';
        }
      }
    }

    读取大文件的时候,可以利用Blob对象的slice方法,将大文件分成小段,逐一读取,这样可以加快处理速度。

  • 相关阅读:
    量化生产力Quantifying Productivity
    计算机视觉和人工智能的状态:我们已经走得很远了 The state of Computer Vision and AI: we are really, really far away.
    量化Hacker News 中50天的数据 Quantifying Hacker News with 50 days of data
    神经网络指南Hacker's guide to Neural Networks
    PHP Error 和 Logging 函数
    PHP 5 Directory 函数
    PHP 5 Date/Time 函数
    PHP cURL 函数
    PHP 5 Calendar 函数
    PHP 5 Array 函数
  • 原文地址:https://www.cnblogs.com/oneplace/p/6171814.html
Copyright © 2011-2022 走看看