Make writing a habit together! This is the second day of my participation in the “Gold Digging Day New Plan · April More text challenge”. Click here for more details.

What are the ways to upload files on the Web? May be a lot of people do not understand, in order to let you know more, xiaobian summed up the following content for you, I hope you can harvest according to this article.

Uploading files is a common requirement for Web development. Uploading files requires a file input field. If you add a multiple attribute to the file input field, you can select multiple files at once (unsupported browsers will automatically ignore this attribute).

<input multiple type="file">
Copy the code

Click the input box to open the Browse file dialog box and select files. Generally, one input box will do just fine. To upload multiple files, you can also use multiple input boxes

Basic Upload Mode

When you put the file input field into the form, you can submit the selected file to the server when submitting the form. Note that since the submitted form contains files, you need to change the encType attribute of the form element to multipart/form-data

<form action="#" enctype="multipart/form-data" method="post">
  <input name="file" type="file">
  <button type="submit">Upload</button>
</form>
Copy the code

This upload method is traditional synchronous upload. If the uploaded file is large, it usually needs to wait for a long time. After the upload is complete, the page will be reloaded, and the operation can be continued only after the upload is complete

Early browsers did not support asynchronous uploads, but you could use iframe to simulate them by hiding an element in a page, specifying a name value, and associating the element’s target attribute with the value of the element’s name attribute

<form action="#" enctype="multipart/form-data" method="post" target="upload-frame">
  <input name="file" type="file">
  <button type="submit">Upload</button>
</form>
<iframe id="upload-frame" name="upload-frame" src="about:blank" style="display: none;"></iframe>
Copy the code

This way, when the form is submitted for upload, the page is not reloaded. Instead, the iframe is reloaded, but the iframe is hidden and is not perceived by the reload

Access to the file

The File API provides the ability to access files through the files property of the input field. This will result in a FileList. This is a set of names

var input = document.querySelector('input[type="file"]')
var file = input.files[0]

console.log(file.name) // File name
console.log(file.size) // File size
console.log(file.type) // File type
Copy the code

Browsers that support the File API can refer to Caniuse

Ajax upload

Since you can access the File content directly through the File API, you can upload the File directly with the XMLHttpRequest object by passing it as a parameter to the SEND method of the XMLHttpRequest object

var xhr = new XMLHttpRequest()
xhr.open('POST'.'/upload/url'.true)
xhr.send(file)
Copy the code

FormData is a constructor that creates a new instance and then adds data to it through the append method of the instance, adding the uploaded file directly to it

var formData = new FormData()
formData.append('file', file, file.name) // The third argument is the file name
formData.append('username'.'Mary') // Additional parameters can also be added
Copy the code

You can even take form elements directly as instantiation parameters so that the entire form’s data is included

var formData = new FormData(document.querySelector('form'))
Copy the code

Once the data is ready, it is uploaded, again as a parameter to the SEND method of the XMLHttpRequest object

var xhr = new XMLHttpRequest()
xhr.open('POST'.'/upload/url'.true)
xhr.send(formData)
Copy the code

Monitor upload progress

The XMLHttpRequest object also provides a progress event based on which you can tell how well the upload is progressing

var xhr = new XMLHttpRequest()
xhr.open('POST'.'/upload/url'.true)
xhr.upload.onprogress = progressHandler // This function is defined next
Copy the code

The uploaded progress event is triggered by the xhr.upload object, whose loaded and total properties are used in the event handler to calculate the progress of the upload

function progressHandler(e) {
  var percent = Math.round((e.loaded / e.total) * 100)}Copy the code

The above calculation results in a number representing the percentage of completion, although these two values may not always be present, so be sure to determine the lengthComputable attribute of the event object first

function progressHandler(e) {
  if (e.lengthComputable) {
    var percent = Math.round((e.loaded / e.total) * 100)}}Copy the code

Browsers that support Ajax uploads can be found at caniuse caniuse.com/#feat=xhr2

Segmentation upload

Using the slice method of a File object, you can slice a File by passing two arguments, a start and an end, which will return a new Blob object containing the portion of the original File from the start to the end. This can be determined by file instanceof Blob, which is the parent of file.)

var blob = file.slice(0.1024) // File from byte position 0 to byte position 1024 that 1KB
Copy the code

Large files can be split into several Blob objects and uploaded separately

function upload(file) {
  let formData = new FormData()
  formData.append('file', file)
  let xhr = new XMLHttpRequest()
  xhr.open('POST'.'/upload/url'.true)
  xhr.send(formData)
}

var blob = file.slice(0.1024)
upload(blob) // Upload the first part

var blob2 = file.slice(1024.2048)
upload(blob2) // Upload the second part

// Upload the rest
Copy the code

It’s usually more convenient to use a loop

var pos = 0 // Start position
var size = 1024 // Block size

while (pos < file.size) {
  let blob = file.slice(pos, pos + size) // End position = start position + block size

  upload(blob)
  pos += size // Continue the split from the end position next time
}
Copy the code

The code that the server receives in chunks for reassembly is not shown here

Uploading files in this way will send multiple HTTP requests at once. How do you handle the situation where multiple requests are sent simultaneously? There are a number of methods that you can use to handle a Promise, make each upload return a Promise object, and then combine them with the promise. all method, which takes an array as an argument, So put the Promise objects returned from each upload in an array

var promises = []

while (pos < file.size) {
  let blob = file.slice(pos, pos + size)

  promises.push(upload(blob)) // upload should return a promise
  pos += size
}
Copy the code

Also modify the upload function to return a promise

function upload(file) {
  return new Promise((resolve, reject) = > {
    let formData = new FormData()
    formData.append('file', file)
    let xhr = new XMLHttpRequest()
    xhr.open('POST'.'/upload/url'.true)
    xhr.onload = () = > resolve(xhr.responseText)
    xhr.onerror = () = > reject(xhr.statusText)
    xhr.send(formData)
  })
}
Copy the code

When it’s all done

Promise.all(promises).then((response) = > {
  console.log('Upload success! ')
}).catch((err) = > {
  console.log(err)
})
Copy the code

Browsers that support file splitting can refer to Caniuse

Checking whether the file object has the method will tell you whether the browser supports it or not. For earlier versions of some browsers, the corresponding browser vendor prefix is required

var slice = file.slice || file.webkitSlice || file.mozSlice

if (slice) {
  let blob = slice.call(file, 0.1024) // call
  upload(blob)
} else {
  upload(file) // Upload the entire file directly without partition support, or the file is too large
}
Copy the code

Drag and drop to upload

The drag-and-drop API enables drag-and-drop file uploads. By default, dragging and dropping a file to the browser will attempt to open the file. To use drag-and-drop, you need to prevent this default behavior

document.addEventListener('dragover'.function(e) {
  e.preventDefault()
  e.stopPropagation()
})
Copy the code

Specify any element as the drop area, and bind the drop event to an element

var element = document.querySelector('label')
element.addEventListener('drop'.function(e) {
  e.preventDefault()
  e.stopPropagation()

  // ...
})
Copy the code

The file is retrieved from the dataTransfer property of the event object and then uploaded

var file = e.dataTransfer.files[0]
upload(file) The // upload function has been defined previously
Copy the code

Choose the type

Add the Accept attribute to the file input box to specify the type of file to be selected. For example, if you want to select a PNG image, specify the value image/ PNG, or if you want to allow all types of images, image/*

<input accept="image/*" type="file">
Copy the code

Capture =”camera” : capture=”camera” : capture=”camera” : Capture =”camera” : Capture =”camera” : Capture =”camera” : Capture =”camera

if (iOS) { // iOS use navigator.userAgent
  input.removeAttribute('capture')}Copy the code

Unsupported browsers automatically ignore these properties

Custom styles

File input fields look different from browser to browser, and styling your input is not always easy. If you need to apply a custom style, a trick is to attach a label element to the file input field. Clicking on the label element triggers the file input field to click. Open the browse file dialog box, equivalent to clicking the file input box effect

<label for="file-input"></label>
<input id="file-input" style="Clip: the rect (0,0,0,0); position: absolute;" type="file">
Copy the code

At this point, you can hide the original file input field and style the label element any way you want. After all, styling the label element is much easier than styling the input element

After reading the above content, do you have any further understanding of how the Web implements file uploading? If you want to know more about the content, welcome to pay attention to the Cloud industry information channel, thank you for reading.