Introduction to the
Front-end upload and download is usually not often used, even if used may be the previous module or third-party library has been written, introduced can be used. But I think as front-end development, file upload and download is very necessary to understand clearly.
This article mainly describes the front-end File upload and download, here may involve some front-end binaries, such as ArrayBuffer, TypedArray, DataView, Blob, File, Base64, FileReader, etc. If this is not clear, you can first read the author of the front-end binary to clarify the article.
download
There are many different ways to download, and each has its own characteristics.
Hyperlink download
Using hyperlinks to complete our front-end download is the most common way. Its main use of the window. The URL. CreateObjectURL (blob) method to generate a blob URL, then blob URL assigned to link href attribute, and then click on the link to download.
A simple way of thinking about it is to convert an object of type file or Blob to a UTF-16 string and store it in memory under the document of the current operation.
The method used to generate the BLOb URL is url.createObjecturl (file/blob). The clearing can only be done by the page unload() event or manually using the URL. RevokeObjectURL (objectURL).
The Download attribute is used to name downloaded files, but note the compatibility of the Download attribute.
Next, I’ll simulate the back end returning ArrayBuffer and Blob objects for hyperlinked downloads.
The backend returns an ArrayBuffer
function aDownload1() {
// The simulated backend returns an ArrayBuffer
const str = "hello randy!";
let ab = new ArrayBuffer(str.length);
let ia = new Uint8Array(ab);
for (let i = 0; i < str.length; i++) {
ia[i] = str.charCodeAt(i);
}
const a = document.createElement("a");
// Set the file name to test
a.download = "test";
// Convert an ArrayBuffer to a bloB
const blob = new Blob([ia], { type: "text/plain" });
// Generate a BLOb URL. You can use Blob objects or File objects
a.href = window.URL.createObjectURL(blob);
a.style.display = "none";
document.body.appendChild(a);
a.click();
// Free memory
window.URL.revokeObjectURL(a.href);
// Remove element A
document.body.removeChild(a);
}
Copy the code
The back end returns a Blob
function aDownload2() {
// The simulated backend returns a Blob
const blob = new Blob(["hello"."randy"] and {type: "text/plain" });
const a = document.createElement("a");
// Set the file name to test
a.download = "test";
// Generate the BLOb URL directly. You can use Blob objects or File objects
a.href = window.URL.createObjectURL(blob);
a.style.display = "none";
document.body.appendChild(a);
a.click();
// Free memory
window.URL.revokeObjectURL(a.href);
// Remove element A
document.body.removeChild(a);
}
Copy the code
ShowSaveFilePicker API to download
ShowSaveFilePicker is a new API that calls this method to display a file selector that allows the user to choose a save path.
const FileSystemFileHandle = Window.showSaveFilePicker(options);
Copy the code
The showSaveFilePicker method supports an optional argument of an object type that can contain the following attributes:
-
ExcludeAcceptAllOption: Boolean type. Default value is false. By default, the selector should include an option not to apply any file type filters (enabled by the types option below). Setting this option to true means that the types option is not available.
-
Types: Array type, representing the list of file types allowed to be saved. Each entry in the array is a configuration object containing the following properties:
Description (Optional)
: Describes the types of files allowed to be saved.accept
: is an object, of that objectkey
是 MIMEType and the value is a list of file extension names.
suggestedName
Recommended file name.
async function download3(blob, filename) {
try {
const handle = await window.showSaveFilePicker({
suggestedName: filename,
types: [{description: "text file".accept: {
"text/plain": [".txt",}}, {description: "jpeg file".accept: {
"image/jpeg": [".jpeg"],},},],});const writable = await handle.createWritable();
await writable.write(blob);
await writable.close();
return handle;
} catch (err) {
console.error(err.name, err.message); }}function showSaveFilePickerDownload() {
// Simulate blob files
const blob = new Blob(["hello"."randy"] and {type: "text/plain" });
download3(blob, "test.txt");
}
Copy the code
When you click download, the following selection screen will appear, which will show your suggested file name and file type selection.
The showSaveFilePicker API allows you to select the file download directory, select the file format, and change the file name. Unfortunately, the API isn’t very compatible at the moment.
FileSaver download
FileSaver. Js is a solution for saving files on the client and is ideal for Web applications that generate files on the client.
Compatibility is as follows
The main thing to remember about Filesaver.js is its saveAs method.
FileSaver.saveAs(
Blob/File/Url,
optional DOMString filename,
optional Object { autoBom }
)
Copy the code
SaveAs method supports three parameters:
The first parameter indicates that it supports Blob/File/Url.
The second parameter indicates the name of the file (optional).
The third parameter indicates the configuration object (optional). Set {autoBom: true} if you want fliesaver.js to automatically provide Unicode text encoding prompt byte order tokens. Note that this can only be done if charset= UTF-8 of blob type is set.
The installation
npm install file-saver --save
Copy the code
The blob data source
const blob = new Blob(["Hello, world!"] and {type: "text/plain; charset=utf-8"});
FileSaver.saveAs(blob, "helloworld.txt");
Copy the code
const canvas = document.getElementById("my-canvas");
canvas.toBlob(function(blob) {
saveAs(blob, "prettyimage.png");
});
Copy the code
The file data source
const file = new File(["Hello, world!"] and {type: "text/plain; charset=utf-8"});
FileSaver.saveAs(file, "helloworld.txt");
Copy the code
Web linked data source
FileSaver.saveAs("https://httpbin.org/image"."image.jpg");
Copy the code
Jszip compressed download
Jszip can convert downloaded files to ZIP format.
Jszip does not have its own download function, it only provides the function of zip file compression, we still need to use the aforementioned FileSaver.
The installation
npm install jszip
Copy the code
use
// Create a JSZip object
var zip = new JSZip();
// Add the file to the JSZip object you created earlier
zip.file("Hello.txt"."Hello World\n");
// Generate JSZip file
zip.generateAsync({type:"blob"}).then(function(content) {
// Filesaver.js is required
FileSaver.saveAs(content, "example.zip");
});
Copy the code
See the official documentation for more information on how to use JsZip
Attachment download
When it comes to attachment download, many small partners may not understand, the following author gives an example you will understand.
We usually enter the link address of the image in the browser, why some images are preview and others are download directly?
This link in your browser to open direct preview is https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ab5e763e993f4bfab3c2ce3ef2935ec6~tplv-k3u1fbpfcp-waterm ark.image
Open this link in your browser is direct download http://pic.96weixin.com/ueditor/20200511/1589185236200665.jpg?x-oss-process=image/resize, m_lfit, w_120
This involves attachment downloading.
We can set the Content-Disposition response header to indicate whether the Content of the response is presented inline or downloaded and saved locally as an attachment. Filename Specifies the name of the file to download.
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="mouth.png"
Copy the code
Open the console and you’ll see that our second image above has the Content-Disposition response header set, so we’ll download the image directly as an attachment after we enter the image link.
upload
In the upload section, either way, you get the file object and then transfer it using the FormData object.
Single file upload
<input id="uploadFile1" type="file" accept="image/*" />
Copy the code
const upload = () = > {
// Get the uploaded input element
const uploadFileEle = document.querySelector("#uploadFile1");
// Get the file
const files = uploadFileEle.files;
let formData = new FormData();
formData.append(fieldName, files[0]);
// make a request
// axios.post(url, formData)
}
Copy the code
Multi-file upload
For multi-file uploads, we only need to tweak it slightly. Add a multiple attribute to the input element to support multiple file uploads.
<input id="uploadFile2" type="file" accept="image/*" multiple />
Copy the code
For JS, we need to add our files in a loop within the form.
const upload = () = > {
// Get the uploaded input element
const uploadFileEle = document.querySelector("#uploadFile2");
// Get the file
const files = uploadFileEle.files;
let formData = new FormData();
Object.values(files).forEach((file, i) = > {
formData.append('file' + i, file);
});
// make a request
// axios.post(url, formData)
}
Copy the code
Folder upload
For folder uploads, we only need to tweak it slightly. Add a webkitDirectory attribute to the input element to indicate a folder upload.
The compatibility of this property is as follows. Note that Internet Explorer does not support this property at all.
<input id="uploadFile3" type="file" accept="image/*" webkitdirectory />
Copy the code
For JS, we need to add our files in a loop within the form.
const upload = () = > {
// Get the uploaded input element
const uploadFileEle = document.querySelector("#uploadFile3");
// Get the file
const files = uploadFileEle.files;
let formData = new FormData();
Object.values(files).forEach((file, i) = > {
formData.append('file' + i, file);
});
// make a request
// axios.post(url, formData)
}
Copy the code
If you upload in folder mode, there will be a little prompt after selecting folder, as follows
And we can see the relative path of the File in the File object with the webkitRelativePath property.
Jszip compressed upload
Compressed upload is to compress a file into a compressed package and upload it to the server. For compression, use the JsZip library we introduced earlier.
Below I use the way of folder upload example.
<input id="uploadFile4" type="file" accept="image/*" webkitdirectory />
Copy the code
function generateZipFile(
zipName,
files,
options = { type: "blob", compression: "DEFLATE" }
) {
return new Promise((resolve, reject) = > {
// Create a JSZip object
const zip = new JSZip();
Object.values(files).forEach((file, i) = > {
// Looping adds the file to the JSZip object you created earlier
zip.file("file" + i, file);
});
// Generate JSZip file
zip.generateAsync(options).then(function (blob) {
zipName = zipName || Date.now() + ".zip";
const zipFile = new File([blob], zipName, {
type: "application/zip"}); resolve(zipFile); }); }); }async function uploadFile() {
// Get the uploaded input element
const uploadFileEle = document.querySelector("#uploadFile4");
// Get the file
const files = uploadFileEle.files;
// Get the relative path
let webkitRelativePath = fileList[0].webkitRelativePath;
// Get the folder name, used as the zip package name
let zipFileName = webkitRelativePath.split("/") [0] + ".zip";
let zipFile = await generateZipFile(zipFileName, fileList);
let formData = new FormData();
formData.append('zipfile', zipFile);
// make a request
// axios.post(url, formData)
}
Copy the code
Drag and drop to upload
To implement drag-and-drop uploads, we need to understand drag-and-drop events. Such as the Drag, Dragend, Dragenter, Dragover, or drop event.
dragenter
: triggered when an element or selected text is dragged to a releasable targetdragover
: Fires when an element or selected text is dragged onto a releasable target (every 100 milliseconds);dragleave
Emitted when a drag element or selected text leaves a releasable target;drop
: Emitted when an element or selected text is released on a releaseable target.
You can check out the MDN official documentation about drag and drop. I won’t go into details here.
The core of drag-and-drop upload is to retrieve the list of files from the Files property of the DataTransfer object, and then upload using FormData.
The core code
dropAreaEle.addEventListener("drop", handleDrop, false);
function handleDrop(e) {
// Get the list of files on the dataTransfer object
const files = e.dataTransfer.files;
let formData = new FormData();
Object.values(files).forEach((file, i) = > {
formData.append("file" + i, file);
});
// make a request
// axios.post(url, formData)
}
Copy the code
Copy and paste upload
For copy and paste we first need to understand the Clipboard object.
We can retrieve the ClipBoard object via navigator.clipboard, and then retrieve the content via navigator.clipboard.read(). But for incompatible items we need to access the contents of the clipboard via E.clipboardData. items.
The following example is to upload an image from a clipboard.
onst IMAGE_MIME_REGEX = /^image\/(jpe? g|gif|png)$/i;
const uploadAreaEle = document.querySelector("#uploadArea");
// Listen for the paste event
uploadAreaEle.addEventListener("paste".async (e) => {
e.preventDefault();
const files = [];
if (navigator.clipboard) {
let clipboardItems = await navigator.clipboard.read();
for (const clipboardItem of clipboardItems) {
for (const type of clipboardItem.types) {
if (IMAGE_MIME_REGEX.test(type)) {
const blob = awaitclipboardItem.getType(type); files.push(blob); }}}}else {
const items = e.clipboardData.items;
for (let i = 0; i < items.length; i++) {
if (IMAGE_MIME_REGEX.test(items[i].type)) {
letfile = items[i].getAsFile(); files.push(file); }}}// With files we can use FormData to upload
let formData = new FormData();
files.forEach((file, i) = > {
formData.append("file" + i, file);
});
// make a request
// axios.post(url, formData)
});
Copy the code
About the FormData
The previous uploads all involve FormData. Many friends may not understand FormData, so the author will explain the relevant API of FormData in detail here.
FormData we can think of as the JS version of a form. The function is similar to our HTML form.
// Create an empty object using the FormData constructor
const formdata = new FormData();
// Append data with the append() method
formdata.append("name"."randy");
// Use the get method to read the value
console.log(formdata.get("name"));//randy
// Use the set method to set the value
formdata.set("name"."demi");
console.log(formdata.get("name"));//demi
// Get all values whose key is age and return values of array type
formdata.getAll("age");
// Check whether data with key as name is included
console.log(formdata.has("name"));//true
// Delete key name
formdata.delete("name");
Copy the code
Instead of creating a new formData, we can initialize it based on an existing form.
<form id="myForm">Name:<input type="text" name="name" value="randy">
</form>
Copy the code
// Get the form element in the page based on the ID
const myForm = document.querySelector("#myForm");
// Initialize formData with the obtained form elements as parameters
const formdata=new FormData(myForm);
console.log(formdata.get("name"));// randy
Copy the code
FormData, similar to Object, supports keys, values, and entries
formData.keys();
formData.values();
formData.entries();
Copy the code
More details about formData can be found in the OFFICIAL MDN documentation
Ali oss upload and download
In addition to uploading and downloading on our own server as described above, we may also encounter uploading and downloading on third-party servers, such as OSS, which we also need to understand. For our front-end, focus on the OSS node documentation.
Refer to the article
For file downloads, it’s enough to understand these nine scenarios
File upload. It’s enough to understand these 8 scenarios
Afterword.
This article is the author’s personal study notes, if there are fallacies, please inform, thank you! If this article has been helpful to you, please click the “like” button. Your support is my motivation to keep updating.