使用FormData数据做图片上传: new FormData() canvas实现图片压缩
使用FormData数据做图片上传: new FormData() canvas实现图片压缩
ps: 千万要使用append不要用set 苹果ios有兼容问题导致数据获取不到,需要后台接口支持formData数据 Content-Type: multipart/form-data
正确的打开方式:formdata.append('file', file)
错误的打开方式:formData.set(name,value)
//html代码
<div class="sendImage" slot="label">
<input type="file" name="file" accept="image/*" ref="ndImgUpload"
class="upload_input" @change="imgSelectChange">
</div> //**************javascript代码 Begin********************** //************* tool.js文件 canvas实现图片压缩*********** // 用于压缩图片的canvas
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d');
// 瓦片canvas
let tCanvas = document.createElement("canvas");
let tctx = tCanvas.getContext("2d"); // /**
// * ************ js图片压缩类*****************
// */
export function compress (img) {
let initSize = img.src.length;
let width = img.width;
let height = img.height; //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
let ratio;
if ((ratio = width * height / 4000000) > 1) {
ratio = Math.sqrt(ratio);
width /= ratio;
height /= ratio;
} else {
ratio = 1;
} canvas.width = width;
canvas.height = height; // 铺底色
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, canvas.width, canvas.height); //如果图片像素大于100万则使用瓦片绘制
let count;
if ((count = width * height / 1000000) > 1) {
count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片 // 计算每块瓦片的宽和高
let nw = ~~(width / count);
let nh = ~~(height / count); tCanvas.width = nw;
tCanvas.height = nh; for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh); ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
}
}
} else {
ctx.drawImage(img, 0, 0, width, height);
} //进行压缩toDataURL:值越小,压缩力度越大
let ndata = canvas.toDataURL('image/jpeg', 0.7); console.log('压缩前:' + initSize);
console.log('压缩后:' + ndata.length);
console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%"); tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0; return ndata;
} /**
* 将以base64的图片url数据转换为Blob
* @param urlData
* 用url方式表示的base64图片数据
*/
export function convertBase64UrlToBlob (urlData) {
let arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = window.atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type: mime});
} /**
* ***********业务代码开始************
*/ import {compress, convertBase64UrlToBlob} from 'utils/tool'
const UPLOAD_IMG_SIZE = 10 //图片上传大小不能大于10M
const IMG_NEED_COMPRESS_SIZE = 0.5 //图片大小<=0.5M,则不压缩,直接上传
const SELECT_IMG_QUANTITY = 9 //发送消息图片最多选9张 // *************vue代码 *************** methods:{
imgSelectChange (e) {
this.$vux.loading.show({
text: 'Loading'
}) let file = e.target setTimeout(() => { //加500ms定时器是为了防止大质量图片上传会造成卡顿loading会延迟执行
this.sendImgIndex = 0 if (file.files.length > SELECT_IMG_QUANTITY) {
this.$vux.loading.hide()
return this.$vux.alert.show({
title: '提示',
content: '最多选9张图片',
onHide () {
file.value = ''
}
})
} for (let obj of Array.from(file.files)) { if (!/\/(?:jpeg|png|gif|jpg)/i.test(obj.type)) {
this.$vux.loading.hide()
return this.$vux.alert.show({
title: '提示',
content: `${obj.name}不是图片文件类型`,
onHide () {
file.value = ''
}
})
} let calcSize = obj.size / 1024 / 1024
if (calcSize > UPLOAD_IMG_SIZE) {
this.$vux.loading.hide()
return this.$vux.alert.show({
title: '提示',
content: `图片大小不能大于${UPLOAD_IMG_SIZE}M`,
onHide () {
file.value = ''
}
})
} } const imgLen = file.files.length
this.eachSendImg(file.files, file, (data) => { //msgType 0系统 1文字 2图片 3音频 4视频 5回撤
this.sendMsgHandle(2, data, () => {
this.sendImgIndex === imgLen && this.$vux.loading.hide()
}, () => {
this.sendImgIndex === imgLen && this.$vux.loading.hide()
this.$vux.alert.show({
title: '提示',
content: `图片${file.files[this.sendImgIndex - 1].name}发送消息失败`
});
}) }, (err) => { })
}, 500)
},
eachSendImg (files, input, success, error) {
if (!files.length) return
let that = this
let args = arguments that.sendImg(files[that.sendImgIndex]).then(data => {
success(data)
that.sendImgIndex++
files[that.sendImgIndex] ? that.eachSendImg.apply(that, args) : input.value = '' }).catch(err => {
that.$vux.loading.hide() let txt_tip = err.msg === 'FILE_WRONG_SIZE' ? `图片${files[that.sendImgIndex].name}文件过大,上传失败`
: `图片${files[that.sendImgIndex].name}上传失败`; that.$vux.alert.show({
title: '提示',
content: txt_tip,
onHide () {
error(err)
that.sendImgIndex++ if (files[that.sendImgIndex]) {
that.$vux.loading.show({
text: 'Loading'
})
that.eachSendImg.apply(that, args)
} else {
input.value = ''
} }
}) }) },
sendImg (file) { let formdata = new FormData(); // FormData 对象
let that = this return new Promise((resolve, reject) => { if (file.size / 1024 / 1024 <= IMG_NEED_COMPRESS_SIZE) { formdata.append('file', file)
that.sendImgAjax(formdata).then((res) => {
resolve(res)
}).catch((err) => {
reject(err)
})
return;
} let reader = new FileReader();
reader.onload = function () {
let result = this.result;
let img = new Image();
img.src = result; // 图片加载完毕之后进行压缩,然后上传
if (img.complete) {
let data = compress(img); let blob = convertBase64UrlToBlob(data);
formdata.append("file", blob, "file_" + Date.parse(new Date()) + ".jpg"); // 文件对象
that.sendImgAjax(formdata).then((res) => {
resolve(res)
}).catch((err) => {
reject(err)
}) img = null;
} else {
img.onload = () => {
let data = compress(img); let blob = convertBase64UrlToBlob(data);
formdata.append("file", blob, "file_" + Date.parse(new Date()) + ".jpg"); // 文件对象
that.sendImgAjax(formdata).then((res) => {
resolve(res)
}).catch((err) => {
reject(err)
}) img = null;
};
} }
reader.readAsDataURL(file);
})
},
sendImgAjax (formData) {
return new Promise((resolve, reject) => {
getData.common.form_uploadImg({
data: formData,
sucCb (data) {
resolve(data)
},
failCb (err) {
reject(err)
}
})
})
},
sendMsgHandle (type, msg, success, error) {//发送消息
if (!this.inputVal.trim() && !msg) return this.$vux.toast.text('消息内容不能为空');
this.disabled = true this.$vux.loading.show({
text: 'Loading'
}) if (this.query.groupId) {
let that = this
getData.doctor.group_chat_send_msg({
params: {
gid: that.query.groupId,
//msg{1 || 0} :如果是图片上传,数据转为字符串,包含宽高url,msgType
msg: msg ? JSON.stringify(msg) : that.inputVal,
type //msgType 0系统 1文字 2图片 3音频 4视频 5回撤
},
sucCb (data) {
msg && (data.msg = JSON.parse(data.msg)) //如果是图片上传,msg消息数据为对象转的字符串
that.data.push({
chatid: data.uid,
from: data.uid,
content: msg ? data.msg.url : data.msg,
width: msg ? data.msg.width : 0,
height: msg ? data.msg.height : 0,
create_time: data.date,
avatar: data.pic,
name: data.nick,
group_id: data.gid,
msg_id: data.id,
msg_type: data.type
}) that.addPrevTimeData()
that.setLocalData(that.query.groupId, that.data.slice(-1)) type !== 2 && that.$vux.loading.hide()
that.disabled = false
that.inputVal = '' success && success()
},
failCb (err) {
type !== 2 && that.$vux.loading.hide()
that.disabled = false
let overtime = err.code * 1 === 0 if (that.inGoBackError(err.code) || overtime) {
type === 2 && that.$vux.loading.hide() that.$vux.alert.show({
title: '提示',
content: overtime ? '发送失败,请检查网络' : err.code === 'USER_NOT_IN_GROUP' ? '您已被移出群聊' : err.msg,
onHide () {
!overtime && that.$router.replace({
path: '/spa/msgGroup'
})
}
});
} else if (type === 2) {
error && error()
} else {
that.$vux.loading.hide()
that.$vux.alert.show({
title: '提示',
content: '消息发送失败'
});
} }
})
}
} }
使用FormData数据做图片上传: new FormData() canvas实现图片压缩的更多相关文章
- ASP.NET Core 简单实现七牛图片上传(FormData 和 Base64)
ASP.NET Core 简单实现七牛图片上传(FormData 和 Base64) 七牛图片上传 SDK(.NET 版本):https://developer.qiniu.com/kodo/sdk/ ...
- Burp Post、Get数据包转为上传multipart/form-data格式数据包
方法一: 新建一个网页进行上传,代码代码如下: <html> <head></head> <body> <form method="po ...
- layui图片上传之后后台如何修改图片的后缀名以及返回数据给前台
const pathLib = require('path');//引入node.js下的一个path模块的方法,主要处理文件的名字等工作,具体可看文档 const fs = require(''fs ...
- input type=file实现图片上传,预览以及图片删除
背景 前两天在做一个PC网站的意见反馈,其中涉及到了图片上传功能,要求可以上传多张图片,并且支持图片上传预览及图片删除, 图片上传这一块以前没怎么搞过,而且一般也很少会碰到这样的需求,所以在做这个功能 ...
- jsp+springmvc实现文件上传、图片上传和及时预览图片
1.多文件上传:http://blog.csdn.net/a1314517love/article/details/24183273 2.单文件上传的简单示例:http://blog.csdn.net ...
- java实现图片上传功能,并返回图片保存路径
1.前端html <div class="form-group"> <label for="inputPassword3" class ...
- 在ASP.NET MVC下实现单个图片上传, 客户端服务端双重限制图片大小和格式, 服务端裁剪图片
在"MVC文件图片ajax上传轻量级解决方案,使用客户端JSAjaxFileUploader插件01-单文件上传"一文中,使用JSAjaxFileUploader这款插件实现了单文 ...
- asp.net多图片上传同时保存对每张图片的描述
前台aspx //图片预览和描述 function previewImage(file) { var div = document.getElementById('preview'); div.inn ...
- php图片上传检测是否为真实图片格式
PHP 图片上传,如果不做任何判断的话,随便一个文件如 rar,zip,php,java等文件改个文件名,改个后缀就能以图片形式上传的服务器,往往会造成极大的危害! 工具/原料 PHP apach ...
- thinkphp图片上传+validate表单验证+图片木马检测+缩略图生成
目录 1.案例 1.1图片上传 1.2进行图片木马检测 1.3缩略图生成 1.4控制器中调用缩略图生成方法 1.案例 前言:在thinkphp框架的Thinkphp/Library/Thin ...
随机推荐
- 【BZOJ5306】[HAOI2018]染色(NTT)
[BZOJ5306]染色(NTT) 题面 BZOJ 洛谷 题解 我们只需要考虑每一个\(W[i]\)的贡献就好了 令\(lim=min(M,\frac{N}{S})\) 那么,开始考虑每一个\(W[i ...
- HDU-3974 Assign the task题解报告【dfs序+线段树】
There is a company that has N employees(numbered from 1 to N),every employee in the company has a im ...
- SCWS中文分词,向xdb词库添加新词
SCWS是个不错的中文分词解决方案,词库也是hightman个人制作,总不免有些不尽如人意的地方.有些词语可能不会及时被收入词库中. 幸好SCWS提供了词库XDB导出导入词库的工具(phptool_f ...
- python基础----元类metaclass
1 引子 class Foo: pass f1=Foo() #f1是通过Foo类实例化的对象 python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载cl ...
- Python之旅:装饰器
装饰器就是闭包函数的一种应用场景 一.为何要用装饰器 开放封闭原则:软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的 也就是说我们必须找到一种解决方案:能够在不修该 ...
- Canny边缘检测算法原理及其VC实现详解(一)
转自:http://blog.csdn.net/likezhaobin/article/details/6892176 图象的边缘是指图象局部区域亮度变化显著的部分,该区域的灰度剖面一般可以看作是一个 ...
- 洛谷P2002 消息扩散
题目背景 本场比赛第一题,给个简单的吧,这 100 分先拿着. 题目描述 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n ...
- Qt ------ 再论事件循环
在介绍在以前,我们要认识两个术语: 可重入的(Reentrant):如果多个线程可以在同一时刻调用一个类的所有函数,并且保证每一次函数调用都引用一个唯一的数据,就称这个类是可重入的(Reentrant ...
- 「Django」学习之路,持续更改
一.setting设置 1.设置 局域网可以部署连接 ALLOWED_HOSTS = ['*.besttome.com','192.168.1.100'] 2.static配置 STATIC_URL ...
- at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:142) :json转化“$ref 循环引用”的问题
原因: entity实体中存在@OneToMany,@ManyToOne注解,在转化json是产生了循环引用 报的错误 解决方法: springmvc @ResponseBody 默认的json转化用 ...