Why the front end to compress the image
- As h5 mobile phone has a powerful photo taking function, pictures are usually 5 or 6 meters long. If you upload them directly in this way, there will be no restriction, which will lead to huge traffic and slow server requests
- The service side upload the image is required to image size, and directly upload such a large image, bandwidth it can not bear, so the front end of the compression of the image has become a necessary link
Compression process
- Use the input tag to retrieve the image file you want to upload
- Convert the image file object to an IMG tag
- Compress and draw on canvas as HTMLImageElement
- Convert canvas drawn images into blob files
- Convert blob files to File objects (depending on background interface)
- Upload blob files or file object files to the server
1. Get the file using the input tag
This step need not say more, after all are very familiar with it… Use the native input tag to set type to File, and then set the Accept attribute to limit the type of file selected. For example, if you want to get an image, set the accept attribute to Image /*, click here and bind the onChange event to get the selected file
<input type="file" accept="image/*" />
Click Select File, get the value, get the file object
2. Convert the obtained image file object to an IMG object
Once you have the image file, turn it into an HTMLImageElement, which is a normal IMG tag, using the FileReader constructor.
Create a new instance of img and fileReader, read the image file via fileReader’s readAsDataURL API, return an encoded Base64 string, and assign this string to the img SRC attribute. This completes the conversion of the image file to the HTMLImageElement.
Const img = new Image() const reader = new fileReader ()// readAsDataURL(file) reader.onload = function(e){ img.src = e.target.result }Copy the code
3. Compress and draw on canvas as HTMLImageElement
Once you have the transformed IMG element, first extract the width of the element, which is the width of the actual image file.
const {width: originWidth, height: originHeight} = img
Then define a maximum width height, if this limit width height is exceeded, scale equally
Const maxWidth = 600,maxHeihgt = 600 let targetWidth = originWidth, TargetHeight = originHeight / / ratio calculation exceeds maximum limit the resized image size of the if (originWidth > maxWidth | | originHeight > maxHeight) {if (originWidth/originHeight > 1) {// Width picture targetWidth = maxWidth targetHeight = math.round (maxWidth * (originHeight /) OriginWidth))} else {// High image targetHeight = maxHeight targetWidth = math.round (maxHeight * (originWidth /) originHeight)) } }Copy the code
After calculating the required size, create a Canvas instance object, set the canvas to the compressed size, and draw img on the canvas
// Create canvas const canvas = document.createElement('canvas') const context = canvas.getContext('2d') // Set width to the size of the image to be compressed canvas.width = targetWidth canvas.height = targetHeight context.clearRect(0, 0, targetWidth, Context. DrawImage (img, 0, 0, targetWidth, targetHeight)Copy the code
4. Convert the canvas image into a BLOB file
After the canvas is drawn, you can use the built-in canvas method toBlob() to convert the drawn image into a BLOB file
canvas.toBlob(function(blob) {
resolve(blob)
}, type || 'image/png')
Copy the code
- The first parametercallbackThe callback function is available as a separate
Blob
Object parameters. - Second parametertype
string
Type that specifies the image format. The default format isimage/png
.optional
Here you can see the toBlob method parameters and how to use them
5. Convert bloB file to file object file (according to background interface)
Convert to BLOb and then to file
const newFile = new File([blob], 'test.png', {
type: type || 'image/png'
})
Copy the code
- The first argument, bits, is an Array containing an ArrayBuffer, ArrayBufferView, Blob, or DOMString object — or any combination of these objects. This is the utF-8 encoded file contents
- The second parameter, name, indicates the file name, or the file path.
File Specifies the parameters and usage of the object instance
6. Upload the BLOb file or file object file to the server.
The complete code
ReadImg (file) {return new Promise((resolve, resolve) reject) => { const img = new Image() const reader = new FileReader() reader.onload = function(e) { img.src = e.target.result } reader.onerror = function(e) { reject(e) } reader.readAsDataURL(file) img.onload = function() { resolve(img) } img.onerror = function(e) { reject(e) } }) }, /** * compressed image *@param img compressed img object *@param type compressed file type *@param MX maximum width limit triggered by compression *@param MH maximum height limit triggered by compression */ compressImg(img, type, mx, mh) { return new Promise((resolve, reject) => { const canvas = document.createElement('canvas') const context = canvas.getContext('2d') const { width: originWidth, height: OriginHeight} = img // maximum size limit const maxWidth = mx const maxHeight = mh // let targetWidth = originWidth let targetHeight = originHeight if (originWidth > maxWidth || originHeight > maxHeight) { if (originWidth / originHeight > 1) {// width picture targetWidth = maxWidth targetHeight = math.round (maxWidth * (originHeight/originWidth))} else {// width picture targetHeight = maxHeight targetWidth = Math.round(maxHeight * (originWidth / originHeight)) } } canvas.width = targetWidth canvas.height = targetHeight context.clearRect(0, 0, targetWidth, DrawImage (img, 0, 0, targetWidth, targetHeight) canvas.toBlob(function(blob) { resolve(blob) }, type || 'image/png') }) },Copy the code
Promise or async await is needed because there are asynchronous operations in the procedure
I’m using async await
async upload(file) { const oFile = file.file const img = await this.readImg(oFile) const blob = await this.compressImg(img, oFile.type, 1024, 1024) const newFile = new File([blob], oFile['name'], { type: oFile.type }) var formData = new FormData() formData.append('file', UploadFile (formData).then(res => {// uploadFile(formData)})},Copy the code