【方法】如何实现图片压缩并使用FormData上传
在前端上传图片的操作过程中,当上传服务器时,如果图片过大,可能会影响页面响应速度,这个时候,我们便会对图片进行压缩处理,再上传服务器。
前端对图片进行压缩,一般使用canvas来实现。最后使用canvas API函数toDataURL来获取图片的Base64字符串,然后上传到服务器的时候,会面临两种选择:
- 直接将图片的Base64字符串post到后端是进行处理和保存;
- 在前端将Base64字符串转化为二进制的Blob对象形式,再使用(FormData)上传至后端。
在上上篇随笔:移动端H5如何调用相册和相机上传图片、音频、视频中有讲到,FormData的append方法中,value接收file和blob对象形式,canvas转化成URL格式后,我们只能通过转为Blob对象上传(我在网上找到的方法都是转为blob...)
第一种方法的话比较简单,主要交给后端进行处理。而第二种相较复杂一点点,主要实现过程如下:
// 本例使用vue-cli3快速构建
<template> <div id="app"> <div class="show-box"> <img :src="imgSrc" alt /> </div> <form class="input-box"> <div class="select"> 选择文件 <input type="file" name="upphoto" @change="input" /> <!--后端读取的是name为upphoto的标签--> </div> <div class="button" @click="loadImg">点击上传</div> </form> </div> </template> <script> import $ from "jquery"; export default { name: "app", data() { return { maxSize: 500, // 限制图片最大为500kb file: "", imgSrc: "", formData: "" }; }, methods: { readFileImg(file) { // 读取图片信息并展示 let reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { let img = new Image(); img.src = reader.result; img.onload = () => { this.imgSrc = img.src;
// 以上是将选择的图片展示出来 let originWidth = img.naturalWidth, originHeight = img.naturalHeight, originSize = file.size / 1024; // 计算图片多少kb this.compressEvent(img, originSize, originWidth, originHeight); }; }; reader.onerror = function(error) { console.log(`error: ${error}`); }; }, compressEvent(img, originSize, originWidth, originHeight) { // 将图片绘制到canvas上进行压缩 let canvas = document.createElement("canvas"), context = canvas.getContext("2d"), maxSize = this.maxSize; if (originSize <= maxSize) { this.formData = new FormData($(".input-box")[0]) return false; } let mul = originSize / maxSize, targetWidth = originWidth / mul, targetHeight = originHeight / mul; canvas.width = targetWidth; canvas.height = targetHeight; context.clearRect(0, 0, targetWidth, targetHeight); // 清除画布 context.drawImage(img, 0, 0, targetWidth, targetHeight); // 画图 let dataURL = canvas.toDataURL("image/jpeg", 0.1); // 将其转化成base64字符串 let blob = this.dataURItoBlob(dataURL); // 转化为blob格式 this.formData = new FormData(); this.formData.append("file", blob, this.file.name); }, dataURItoBlob(dataURI) { // base64格式转化为blob对象 let byteString = atob(dataURI.split(",")[1]); let mimeString = dataURI .split(",")[0] .split(":")[1] .split(";")[0]; let ab = new ArrayBuffer(byteString.length); let ia = new Uint8Array(ab); for (let i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ab], { type: mimeString }); }, input(event) { // 选择文件 this.readFileImg(event.target.files[0]); }, loadImg() { // 点击上传 $.ajax({ url: "./downFile.php", // 接口地址 type: "POST", async: false, data: this.formData, cache: false, contentType: false, processData: false, success: function(data) { this.imgSrc = ""; }, error: function(error) { console.log(error); } }); } } }; </script> <style lang="less">
// 此处样式文件省略...</style>
【参考文章】