Compatibility check

ifFileReader && window.filelist && window.blob) {// Support File APIs}else{// File APIs not supported}Copy the code

FileReader()

The FileReader object lets a Web application asynchronously read the contents of a file (or raw data buffer) stored on a user’s computer. In JavaScript, a FileReaderd object is read by passing in two corresponding objects (File and Blob), and this method can also be used in Web Workers.

FileReader includes four options for reading files asynchronously:

  • FileReader.readAsBinaryString(Blob|File)– The result attribute of the returned value will contain file/blob data as a binary string. Each byte is represented by an integer in the range [0..255].
  • FileReader.readAsText(Blob|File, opt_encoding)– The result attribute of the returned value will contain file/blob data as a text string. The string is encoded in UTF-8 by default. Other formats can be specified using the optional encoding parameter.
  • FileReader.readAsDataURL(Blob|File)– The result attribute of the returned value will contain file/blob data encoded as the data url.
  • FileReader.readAsArrayBuffer(Blob|File)– The result property of the returned value will contain file/blob data in the form of an ArrayBuffer object.

After a FileReader object calls one of these read methods, its progress can be tracked using onloadStart, onProgress, onLoad, onAbort, onError, and onloadEnd.

Read files and display progress

The following example filters out the image from the user-selected content, calls reader.readasdataURL () on the file, and renders the thumbnail by setting the “SRC” property to the data url.

<style>
    .thumb {
        height: 75px;
        border: 1px solid # 000;
        margin: 10px 5px 0 0;
    }

    #list {
        border: 1px solid lightgrey;
        padding: 15px;
        text-align: center;
    }

    #progress_bar {
        margin: 10px 0;
        padding: 3px;
        border: 1px solid # 000;
        font-size: 14px;
        clear: both;
        opacity: 0;
        -moz-transition: opacity 1s linear;
        -o-transition: opacity 1s linear;
        -webkit-transition: opacity 1s linear;
    }

    #progress_bar.loading {Opacity: 1.0; }#progress_bar .percent {
        background-color: #99ccff;
        height: auto;
        width: 0;
    }
</style>


<body>
    <input type="file" name="files[]" id="files" multiple />
    <div id="list"></div>
    <button onclick="abortRead();">Cancel read</button>
    <script>
    let reader;
    let progress;
    let progress_bar;

    function abortRead() {
        reader.abort();
    }

    function errorHandler(evt) {
        let error = evt.target.error;

        switch (error.code) {
            case error.NOT_FOUND_ERR:
                alert('File not found');
                break;
            case error.NOT_READABLE_ERR:
                alert('Unable to read file');
                break;
            case error.ABORT_ERR:
                break;
            default:
                alert('File read error'); }}function updateProgress(evt) {
        if (evt.lengthComputable) {
            let percentLoaded = Math.round((evt.loaded / evt.total) * 100);
            
            if (percentLoaded < 100) {
                progress.style.width = percentLoaded + The '%';
                progress.textContent = percentLoaded + The '%'; }}}function handleFileSelect(evt) {
        letfiles = evt.target.files; // Create a progress bar progress_bar = document.createElement(progress_bar = document.createElement)'div');
        progress_bar.id = 'progress_bar';
        progress = document.createElement('div');
        progress.className = 'percent';
        progress.style.width = '0%';
        progress.textContent = '0%';
        progress_bar.appendChild(progress);
        document.getElementById('list').appendChild(progress_bar);

        for (let i = 0; i < files.length; i++) {
            reader = new FileReader();
            if(! files[i].type.match('image.*')) {
                alert('The selected file is not a picture');
                abortRead();
                return;
            }
            reader.onerror = errorHandler;
            reader.onprogress = updateProgress;

            reader.onabort = (e) => {
                alert('File reading cancelled');
            };

            reader.onloadstart = (e) => {
            	progress_bar.className = 'loading';
            };

            reader.onload = (e) => {
            	
            	let span = document.createElement('span');
                span.innerHTML = ['<img class="thumb" src="', e.target.result, '" title="', files[i].name, '" / >'].join(' ');
                document.getElementById('list').insertBefore(span, progress_bar);
                progress.style.width = '100%';
                progress.textContent = '100%';
            };
            reader.readAsDataURL(files[i]);
        }
    }

    document.getElementById('files').addEventListener('change', handleFileSelect, false);
    </script>
</body>
Copy the code

See the Pen FileReader Demo by Lu (@smallbone) on CodePen.

FileList API

It is literally an array of multiple File objects, but only has the length property and the item(index) method. You can access the File object using either files.item(index) or the files[index] method.

File API

A File object is a specific type of Blob. FileReader, url.createObjecturl (), createImageBitmap(), and xmlHttprequest.send () all accept Blobs and Files.

  • Information contained in the File object
{
	lastModified: 1428005315000,
	lastModifiedDate: Thu Apr 02 2015 15:08:35 GMT-0500 (CDT),
	name: "profile.pdf",
	size: 135568,
	type: "application/pdf",
	webkitRelativePath: ""
}
Copy the code

Note that type is based on the file extension, so it’s not very reliable. Using the information in the File object above, you can implement some common functions, such as limiting the size of the File to be uploaded, and initially limiting the type of the File to be uploaded (this can also be done through the Accept attribute of the input element, but the final type validation is still done on the server side).

The File object is usually obtained from the FileList object returned by:

  1. <input type="file">The elements of the
  2. Drag and drop the DataTransfer object for the operation
  3. By calling on an HTMLCanvasElementmozGetAsFile() API

Select the file through input

/* Assume that the input element is <inputtype="file" id="upload"Multiple > */ // Multiple indicates that multiple files can be uploaded at a timelet uploadInput = document.getElementById('upload');
uploadInput.addEventListener('change', () = > {let fileList = uploadInput.files;
	console.log(fileList);
});
Copy the code

Since FileList objects do not have a forEach() method, it is generally necessary to iterate through each of them through a for loop:

for (var i = 0; fileCount = fileList.length; i < fileCount; i++) {
	console.log(fileList[i]);
}
Copy the code

But we can also use the forEach() method in other ways:

[].foreach. Call (fileList, (file, I, fileList)=>{... }); / / 2. Array ES6 method. The from (uploadInput). ForEach ((I) = > {... });Copy the code

Select the file by drag&drop

Drag events:

  • Drag (start dragging, continue the event)
  • Release the mouse or press ESC to end the drag
  • Dragenter (when entering a valid drag area)
  • Dragexit (when an element is no longer the direct selection target for a drag operation)
  • Dragleave (when leaving a valid drag area)
  • Dragover (to continue the event while hovering in a valid drag area)
  • dragstart
  • Drop (when the target is placed in a valid drag area)

Two points should be noted:

  1. If the Dragover event does not block the default event, the drop event will not be emitted.
  2. Dragexit and dragleave trigger differently in different browsers, dragexit will never trigger in Chrome.
// Drag and display area <div id="drop_zone">Drop files here</div>
<output id="list"></output>

<script>
	functionhandleFileSelect(evt) { evt.stopPropagation(); evt.preventDefault(); // Note that this is no longer target.fileslet files = evt.dataTransfer.files;
		let output = [];
		
		[].forEach.call(files, (file)=>{
			output.push('<li><strong>', file.name, '</strong> (', file.type || 'n/a'.'-', (file.size/1024).toFixed(3), ' Kb, last modified date: ', file.lastModifiedDate.toLocaleDateString(), '</li>');
		});
		document.getElementById('list').innerHTML = '<ul>' + output.join(' ') + '</ul>';	
	}

	function handleDragOver(evt) {
		evt.stopPropagation();
		evt.preventDefault();
		evt.dataTransfer.dropEffect = 'copy';
	}

	let dropZone = document.getElementById('drop_zone');
	dropZone.addEventListener('dragover', handleDragOver, false);
	dropZone.addEventListener('drop', handleFileSelect, false);
</script>
Copy the code