preface

Before the advent of THE HTML5 File API, front-end operations on files were very limited and mostly needed to be implemented in conjunction with the back-end. For security reasons, it is impossible for the code to get the local address of the file when uploading from the local user, so it is impossible for the pure front end to do something like image preview. But the File API makes this possible.

Learn more about the powerful File API.

FileList

The FileList object is the file control of a form. When the user selects a file using the File control, the value of the Files property of the control is a FileList object. It is similar to an array in structure and contains multiple files selected by the user. If the File control does not have a multiple property, then the user can only select one file, so there is only one element in a FileList object.

 type='file' multiple />

    document.querySelector('input').onchange = function() {
      console.log(this.files);
    };
Copy the code

For example, if I select two files, the console prints:

FileList {0: File, 1: File, length: 2}
0: File
1: File
  length:2
__proto__: ObjectCopy the code

In addition to the File control, you can also get a FileList object by dragging and dropping it. For drag-and-drop, check out my previous article HTML5 — making drag-and-drop popular.



  var ipt = document.querySelector('textarea');
  ipt.ondragover = function () { return false; };

  // Add drop handler
  ipt.ondrop = function(e) {
    e.stopPropagation();
    e.preventDefault();
    e = e || window.event;
    var files = e.dataTransfer.files;

    console.log(files);
  };
Copy the code

Select the two files and drag them to the text box to print the same results as above.

In general, it is not possible to construct a FileList object by hand. It can only be read passively. That is, js can access a FileList only if the user actively triggers a file read.

File

We see a FileList object that contains the selected File object. What are the properties of a File? We can print it out and look at it.

  • Name: indicates the file name. This property is read-only.
  • Size: indicates the file size, in bytes. This property is read-only.
  • Type: MIME type of the file. If the type is not discernible, it is an empty string. This property is read-only.
  • LastModified: time when the file was lastModified. The format is timestamp.
  • LastModifiedDate: Time when the file was last modified in the format of Date object instance.

Blob

As you can see from above, File objects inherit from blobs. What is a Blob?

A Blob (Binary Large Object) Object represents a piece of Binary data and provides a series of interfaces for manipulation. Other apis for manipulating binary data, such as File objects, are built on top of Blob objects, inheriting their properties and methods.

There are two ways to generate Blob objects: either by using the Blob constructor, or by slicing out a portion of an existing Blob object using the slice method.

(1) The Blob constructor takes two arguments. The first argument is an array containing the actual data, and the second argument is the type of the data, neither of which is required.

var a = ["hello", "world"];
var myBlob = new Blob(a, { "type" : "text/xml" });
console.log(myBlob);Copy the code

(2) The slice method of Blob object, which divides binary data into bytes and returns a new Blob object.

var a = ["hello", "world"];
var myBlob = new Blob(a, { "type" : "text/xml" });
var newBlob = myBlob.slice(0, 5);
console.log(newBlob);Copy the code

Blob objects have two read-only properties:

  • Size: indicates the size of binary data, in bytes. (The front end can judge whether the file size is appropriate when the file is uploaded)
  • Type: MIME type of binary data, all lowercase, empty string if the type is unknown. (You can determine whether the file type is appropriate in the front end when uploading the file)

FileReader

The FileReader API is the key to the next few tasks. The FileReader API is used to read files, that is, to read the contents of a file into memory. It takes a File object or a Blob object.

FileReader provides different ways to read files for different types of files.

  • ReadAsBinaryString (Blob | File) : binary string, the string each byte contains an integer between 0 and 255.(Abandoned)
  • ReadAsText (Blob | File, opt_encoding) : returns a text string. By default, the text encoding format is UTF-8, and you can specify text in other encoding formats with optional format parameters.
  • ReadAsDataURL (Blob | File) : returns a Base64 encoding based data – a uri object.
  • ReadAsArrayBuffer (Blob | File) : returns a ArrayBuffer object.

In addition to these four different methods of reading files, the FileReader API also has an abort method that is used to abort file uploads.

var reader = new FileReader();
reader.abort();Copy the code

The FileReader object reads files asynchronously and can specify callbacks for a series of events.

  • Onabort method: Triggered when read abort or when the reader.abort() method is called.
  • Onerror method: triggered when reading error.
  • Onload method: triggered after successful reading.
  • Onloadend method: fired after reading, whether successful or not. The triggering sequence comes after onload or onError.
  • Onloadstart method: triggered when reading is about to start.
  • Onprogress method: triggered periodically during reading. (Can be used to obtain the progress of file reading)

When I was learning the base64 encoding of pictures, I wrote an article about several ways to get the base64 encoding of pictures. At that time, I had not learned the File API, and I learned that the File API can also do similar things. Now I have learned that, Write a simple demo hanzichi. Making. IO / 2016 / image2… , not only can obtain the image of the Base64 encoding, but also can obtain the text of the Base64 encoding, the code is relatively simple not to put, can be stabbed here.

Get the base64 encoding of the file, do some functions such as image preview, also handy, interested can try their own, similar to text preview ah, and so on.

URL

Did you think that was it for the File API? No, there’s one more powerful thing I haven’t covered, the URL object!

Calling the createObjectURL method on the URL object, passing in either a File object or a Blob object, generates a link that sounds silly.

var objecturl =  window.URL.createObjectURL(blob);Copy the code

The above code generates a URL for the binary data, which can be placed anywhere a URL would normally be placed, such as the SRC attribute of the IMG tag. Note that every time the url.createObjecturl method is called, you get a different URL, even with the same binary data.

The existence time of this URL, equal to the existence time of the web page, once the page is refreshed or uninstalled, this URL is invalid. RevokeObjectURL is also a manual way to invalidate the URL. RevokeObjectURL

window.URL.revokeObjectURL(objectURL);Copy the code

Let’s take a simple example.

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);Copy the code

A hyperlink is generated to download a file called A.txt that says Hello Hanzichi.

Here, as an aside, is a brief introduction to the new DOWNLOAD properties of H5. For some file types that cannot be opened directly by the browser, such as EXE and RAR, we can generally directly use an A label to point to the address of the file on the server and click to download it. But if it is some browser can directly open the file, such as TXT, JS and so on, if set up a hyperlink, click will directly open the file, generally we can cooperate with the back-end implementation, such as PHP.

$file_name = "1.txt"; $file_dir = dirname(__FILE__). '/'; // Enter the file label Header(" content-type: text/plain"); Header("Content-Disposition: attachment; filename=" . $file_name );Copy the code

The above code requires the file’s content-Type attribute value, amway a website, tool.oschina.net/commons, a variety of file types of the content-Type attribute value!

Header + fread may be more rigorous if security is considered.

$file_name = "1.txt"; $file_dir = dirname(__FILE__). '/'; Header(" content-type: text/plain"); Header("Content-Disposition: attachment; filename=" . $file_name ); echo fread($file, filesize($file_dir . $file_name));Copy the code

But now we just need to add download to the A tag!

 href="1.txt" download>download txt>Copy the code

You can also assign a property value to Download, which is the file name of the download.

 href="1.txt" download="2.txt">download txt>Copy the code

You can omit the.txt suffix, and the browser will use its discretion.

Let’s go back to the URL. For File or Blob objects, we can understand that their existence depends on the page, and the URL can give these “transient” binary objects a temporary address to point to.

What is the use of this temporary address? Can also do image preview, compared to the previous implementation with readAsDataURL, much easier.

 type='file' multiple />

/> document.querySelector("input").onchange = function() { var files = this.files; document.querySelector("img").src = window.URL.createObjectURL(files[0]); } Copy the code

For example, there is a requirement that the front-end upload file, to dynamically generate the download link of the file, can also be done with the URL.

Canvas & dataURL & Blob

There is a toDataURL function in canvas, which can convert Canvas into Base64 encoding in the form of dataURL, and Blob can also convert dataURL. Can they be converted to each other? Is there anything practical about it?

(1) Canvas -> dataURL

Using the toDataURL method is relatively simple, not much to say.

(2) blob -> dataURL

Use FileReader’s readAsDataURL method, as shown in this demo

DataURL -> blob

This function is kind of cool

function dataURLtoBlob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?) ; /)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], {type:mime}); }Copy the code

dataURl-canvas

Set the SRC property of image to dataURL and draw it with the drawImage method.

(5) Blob-canvas

How to draw binary images on canvas? ReadAsDataURL to dataURL, and then (4).

(6) Canvas Blob

Canvas can also be converted to BLOB by using dataURL as a springboard. First, canvas is converted to dataURL (1) and then dataURL is converted to BLOB (3).

What fun things can you do with these transitions? For example, you can upload pictures, do all kinds of processing on them, and then save them. It looks like fun, and then make a demo when you are free.

Read more

The File API also provides many cool features, such as viewing onprogress, splitting files, reading files in segments, and using Ajax. If you are interested, check out the literature below.