本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《
阿里云开发者社区用户服务协议
》和
《
阿里云开发者社区知识产权保护指引
》。如果您发现本社区中有涉嫌抄袭的内容,填写
侵权投诉表单
进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在前端页面,我们通常会遇到需要用户上传图片的操作,可能还会在前端进行图片编辑的操作(比如头像的选区裁剪),然后如果图片过大的话,我们还会对图片进行压缩。这些功能我们通常通过Canvas来进行,最后使用Canvas API函数toDataURL来得到图片的Base64字符串,然后当我们要上传到后台的时候,会面临2种选择:
直接将图片的Base64字符串Post到后端进行处理和保存
在前端将Base64字符串转换成二进制的Blob对象形式,再使用常规的文件上传形式(即FormData)来将其上传到后端
第一种方式对前端来说比较简单,主要的处理逻辑在后端。而第二种的话前端的工作就稍微复杂一些。考虑到后端采用接收二进制文件的方式来处理文件上传的情况比较多,所以我们来看一下前面所说的第二种情况在前端怎么来实现,以下是主要的示例代码:
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>使用FormData上传压缩裁剪后的图片Blob对象</title>
</head>
<input type="file" name="myfile" id="myfile" onchange="uploadHandler(event)">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
function uploadHandler(e) {
var files = e.target.files || e.dataTransfer.files;
if (files && files.length > 0) {
var file = files[0];
resizeImage(file).then(function (result) {
return typeof result === 'string' ? convertToBlob(result, file.type) : result;
}).then(function (blob) {
// 构建FormData
var formData = new FormData();
//注意:此处第3个参数最好传入一个带后缀名的文件名,否则很有可能被后台认为不是有效的图片文件
formData.append("file", blob, file.name);
// 上传文件
$.ajax({
url: '/api/upload',
method: "POST",
data: formData,
cache: false,
processData: false,
contentType: false
}).then(function (res) {
console.log(res);
}).catch(function (err) {
console.log(err);
* 压缩裁剪图片
function resizeImage(file) {
return new Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function () {
var img = new Image();
img.onload = function () {
var w = this.naturalWidth;
var h = this.naturalHeight;
var maxW = 500;
var maxH = 500;
// 如果图片尺寸小于最大限制,则不压缩直接上传
if (w <= maxW && h <= maxH) {
resolve(file);
return;
var level = 0.6;
var multiple = Math.max(w / maxW, h / maxH);
var resizeW = w / multiple;
var resizeH = h / multiple;
var canvas = document.createElement("canvas");
canvas.width = resizeW;
canvas.height = resizeH;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, resizeW, resizeH);
var base64Img = canvas.toDataURL(file.type, level);
var arr = base64Img.split(",");
resolve(arr[1]);
img.src = this.result;
reader.readAsDataURL(file);
* 将图片的base64字符串转换为Blob对象
function convertToBlob(base64Str, fileType) {
var base64 = window.atob(base64Str);
var len = base64.length;
var buff = new ArrayBuffer(len);
var uarr = new Uint8Array(buff);
for (var i = 0; i < len; i++) {
uarr[i] = base64.charCodeAt(i);
var blob = null;
try {
blob = new Blob([buff], { type: fileType });
} catch (e) {
var BlobBuilder = window.BlobBuilder = (
window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder
if (e.name === "TypeError" && BlobBuilder) {
var builder = new BlobBuilder();
builder.append(buff);
blob = builder.getBlob(fileType);
return blob;
</script>
</body>
</html>
代码中值得注意的一点是下面这行代码:
formData.append("file", blob, file.name);
如果不传第三个参数的话,生成的表单数据中,上传文件对应的filename会被设置为blob
: