Appearance
Operating Files
In HTML forms, the only control that allows file uploads is <input type="file">
.
Note: When a form includes <input type="file">
, the form's enctype
must be specified as multipart/form-data
, and the method must be specified as post
for the browser to correctly encode and send the form data in multipart/form-data
format.
For security reasons, browsers only allow users to click <input type="file">
to select local files. Assigning a value to <input type="file">
via JavaScript has no effect. After a user selects a file for upload, JavaScript cannot obtain the actual file path:
Files to upload:
Typically, uploaded files are processed by a backend server. JavaScript can perform checks on file extensions upon form submission to prevent users from uploading invalid file formats:
javascript
let f = document.getElementById('test-file-upload');
let filename = f.value; // 'C:\fakepath\test.png'
if (!filename || !(filename.endsWith('.jpg') || filename.endsWith('.png') || filename.endsWith('.gif'))) {
alert('Can only upload image file.');
return false;
}
File API
Due to JavaScript's limited capabilities in handling user-uploaded files, especially in reading file contents, many web applications resorted to third-party plugins like Flash for file operations.
With the rise of HTML5, the new File API allows JavaScript to read file contents and obtain more file information.
The HTML5 File API provides two main objects: File
and FileReader
, which allow you to access file information and read files.
The following example demonstrates how to read a user-selected image file and preview it in a <div>
:
html
<div class="demo">
Image Preview:
<div id="test-image-preview"></div>
<input type="file" class="demo" id="test-image-file" placeholder="xiuam">
<div id="test-file-info"></div>
</div>
javascript
let fileInput = document.getElementById('test-image-file'),
info = document.getElementById('test-file-info'),
preview = document.getElementById('test-image-preview');
// Listen for change event:
fileInput.addEventListener('change', function () {
// Clear background image:
preview.style.backgroundImage = '';
// Check if a file is selected:
if (!fileInput.value) {
info.innerHTML = 'No file selected';
return;
}
// Get File reference:
let file = fileInput.files[0];
// Get File information:
info.innerHTML = 'File: ' + file.name + '<br>' +
'Size: ' + file.size + '<br>' +
'Last Modified: ' + file.lastModified;
if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {
alert('Not a valid image file!');
return;
}
// Read the file:
let reader = new FileReader();
reader.onload = function(e) {
let data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64 encoding)...'
preview.style.backgroundImage = 'url(' + data + ')';
};
// Read the file as DataURL:
reader.readAsDataURL(file);
});
The above code demonstrates how to read file contents using the HTML5 File API. The file read as a DataURL is a string, similar to data:image/jpeg;base64,/9j/4AAQSk...(base64 encoding)...
, commonly used to set images. For server-side processing, you can send the base64 string (after base64,
) to the server and decode it to obtain the original file's binary content.
Callbacks
The above code also illustrates an important feature of JavaScript: its single-threaded execution model. In JavaScript, the browser's JavaScript engine always executes JavaScript code in a single-threaded mode, meaning that at any point, only one thread of JavaScript code can be executed.
You may wonder how JavaScript handles multiple tasks in a single-threaded model.
In JavaScript, executing multiple tasks is achieved through asynchronous calls. For example, the code:
javascript
reader.readAsDataURL(file);
initiates an asynchronous operation to read file content. Since it is asynchronous, we don't know when the operation will finish, so we need to set up a callback function:
javascript
reader.onload = function(e) {
// This function is automatically called when the file reading is complete:
};
When the file reading is complete, the JavaScript engine will automatically call the callback function we set. By the time the callback function executes, the file has been fully read, allowing us to safely access the file content within the callback.