Vue实现图片转Base64上传案例
- 一、前端图片转Base64
- 二、后台Base64转图片
- 三、前端Base64转图片
一、前端图片转Base64
获取图片,将图片转为Base64字符串,AJAX提交到后台进行处理,前端使用了Vue基础。但是这种做法会比较复杂,后续会使用vant框架实现。
<!--上传图片-->
<div style="width: 90%;margin-left: 5%;margin-top: 30px">
<div class="pics" v-for='(value, key) in imgs' style="text-align:center;float: left;width: 19%;">
<div class="onepicdiv" style="float:left;width: 100%;">
<div>
<img class="onepic" :id=key :src="getObjectURL(value)" style="width: 85%;" @click="showImgs(value)">
</div>
<div @click="delImg(key)" style="color: #999999;width: 100%;font-size: 13px;color: #999999;position: relative;top: -63px;left: 26px">
<van-icon name="close" color="rgb(0,0,0)"/>
</div>
</div>
</div>
<div v-if="imgLen>=5 ? false : true">
<div class="addpicture">
<input id="myfile" type="file" @change="addImg" ref="inputer" multiple accept="image/*"
style="opacity:0;width: 100%;"/>
</div>
</div>
<div style="font-size: 10px;padding-top: 40px;color: #999999"> {{imgLen}}/5</div>
</div>
<!--放大图片时被放大的图片和图片列表之间的遮罩层-->
<div id="showpicmask">
<div v-show="show" @click="back()"
style="position: fixed;z-index: 100;height: 100vh;width: 100%;background-color: rgba(0,0,0,0.95) ">
</div>
</div>
<!--被放大的图片-->
<div id="showpic">
<div v-show="show" @click="back()"
style="position: fixed;z-index: 101;width:100%;height: 100vh;display: flex;float: left;align-items: center;justify-content: center;">
<img :src="picpath" style="width: 100vw;">
</div>
</div>
<script>
//上传图片
addImg(event) {
let inputDOM = this.$refs.inputer;
// 通过DOM取文件数据
this.fil = inputDOM.files;
let oldLen = this.imgLen;
let len = this.fil.length + oldLen;
if (len > 5) {
alert('最多可上传5张,您还可以上传' + (5 - oldLen) + '张');
return false;
}
for (let i = 0; i < this.fil.length; i++) {
let size = Math.floor(this.fil[i].size / 1024);
if (size > 3 * 1024) {
layer.msg('请选择3M以内的图片');
return false;
}
for(key in this.imgs){
if(key == this.fil[i].name){
layer.msg("请勿上传同一张图片")
return
}
}
this.imgLen++;
this.$set(this.imgs, this.fil[i].name , event.target.files[i]);
//转换为base64
let self = this;
let reader = new FileReader();
reader.readAsDataURL(event.target.files[i]);
if (size > 1024) {//图片大于1M,进行压缩
if (typeof (FileReader) === 'undefined') {
console.log("当前浏览器内核不支持base64图标压缩");
//调用上传方式 不压缩
} else {
var file = event.target.files[i];
if (!/image\/\w+/.test(file.type)) {
alert("请确保文件为图像类型");
return false;
}
//压缩图片
reader.onload = function (event) {
if (reader.readyState === 2) {
let image = new Image() //新建一个img标签(不嵌入DOM节点,仅做canvas操作)
image.src = event.target.result; //让该标签加载base64格式的原图
image.onload = function () {
let canvas = document.createElement('canvas'), //创建一个canvas元素
context = canvas.getContext('2d'), //context相当于画笔,里面有各种可以进行绘图的API
imageWidth = image.width / 2, //压缩后图片的宽度,这里设置为缩小一半
imageHeight = image.height / 2, //压缩后图片的高度,这里设置为缩小一半
data = '' //存储压缩后的图片
canvas.width = imageWidth //设置绘图的宽度
canvas.height = imageHeight //设置绘图的高度
//使用drawImage重新设置img标签中的图片大小,实现压缩。drawImage方法的参数可以自行查阅W3C
context.drawImage(image, 0, 0, imageWidth, imageHeight)
//使用toDataURL将canvas上的图片转换为base64格式
data = canvas.toDataURL('image/jpeg')
var st = data.indexOf(',');
var stnew = parseInt(st) + 1;
data = data.substring(stnew);
self.$set(self.filelist, self.fil[i].name, data);
};
}
}
}
} else {
reader.onload = function (event) {
self.headImg = event.target.result; //img base64
var st = self.headImg.indexOf(',');
var stnew = parseInt(st) + 1;
self.headImg = self.headImg.substring(stnew);
self.$set(self.filelist, self.fil[i].name, self.headImg);
}
}
}
},
getObjectURL(file) {
const that = this;
var url = null;
if (window.createObjectURL != undefined) { // basic
url = window.createObjectURL(file);
} else if (window.URL != undefined) { // mozilla(firefox)
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) { // webkit or chrome
url = window.webkitURL.createObjectURL(file);
}
return url;
},
//删除图片
delImg(key) {
const that = this;
this.$delete(that.filelist, key);
this.$delete(this.imgs, key);
this.imgLen--;
},
//放大图片
showImgs(value) {
var url = this.getObjectURL(value);
picmask.show = true
showpic.show = true
showpic.picpath = url
},
</script>
二、后台Base64转图片
后台获取前端Base64字符串,这里在后台转换为图片,存放到指定目录,并将新定义的图片名保存至数据库
//DataObject.java用于存储key-value类型数据的数据结构
//DataStore.java用于存储列表格式数据的数据结构。
//图片处理
DataObject objfile= DataObject.parseJSON(files);
DataStore fileds = DataStore.getInstance();
Set<String> keySet = objfile.keySet();// vdo里的键都是string
Iterator<String> it = keySet.iterator();// 开始遍历
String key;// vdo的键
Object value;// 值(数据类型待判断)
int n=0;
while (it.hasNext()) {
key = it.next();
value = objfile.get(key);
if (value instanceof String) {
//System.out.println("key=="+key +",value="+value);
fileds.put(n, "imgname", key);
fileds.put(n, "imgbase", value);
} else {
throw new BizException("files不是一个String类型的值");
}
n++;
}
if(fileds.rowCount()>0){
DataObject returnobj = DataObject.getInstance();
DataStore urlds = DataStore.getInstance();
for (int j = 0; j < fileds.rowCount(); j++) {
String imgStr = fileds.getString(j, "imgbase");
String FILEPATH = picurl + suggestImgs;
Calendar tempewmscsj = Calendar.getInstance();
long sjid = tempewmscsj.getTimeInMillis();
String idstr = String.valueOf(sjid);
String nowstr = DateUtil.getCurrentTime();
String fileName = "img_" + nowstr + "_" + idstr + ".jpg";
fileNames = fileNames + ";" + fileName;
//对字节数组字符串进行Base64解码并生成图片
String imgUrl = "";
//图像数据为空
if (StringUtils.isBlank(imgStr)) {
returnobj.put("retuendata", imgUrl);
}
BASE64Decoder decoder = new BASE64Decoder();
byte[] b = decoder.decodeBuffer(imgStr);
for (int i = 0; i < b.length; ++i) {
//调整异常数据
if (b[i] < 0) {
b[i] += 256;
}
}
//文件目录不存在则创建
File outFile = new File(FILEPATH);
if (!outFile.exists()) {
outFile.mkdirs();
}
//文件最终的存储位置
File dest = new File(FILEPATH + File.separator + fileName);
//判断目标文件所在的目录是否存在
if (!dest.getParentFile().exists()) {
//创建目录
if (!dest.getParentFile().mkdirs()) {
returnobj.put("retuendata", imgUrl);
}
}
//新生成的图片
imgUrl = FILEPATH + File.separator + fileName;
//这种写法不需要flush或者close 会自动关闭 FileOutputStream 实现了java中的java.lang.AutoCloseable接口。
try (OutputStream out = new FileOutputStream(FILEPATH + File.separator + fileName);) {
out.write(b);
} catch (Exception e) {
//logger.info("Base64Util GenerateImage e:" + e.getLocalizedMessage());
} finally {
returnobj.put("retuendata", imgUrl);
}
urlds.put(j, "imgurl", returnobj.getString("retuendata"));
}
}
//数据库中存放新定义的图片名等信息
...
三、前端Base64转图片
如果选择第二步在后台直接存储Base64字符串到数据库,则可以在前端把Base64转为图片
let file = img.src; // 把整个base64给file
let name = filename + ".png"; // 定义文件名字(例如:cober.png)
var type = "image/png"; // 定义图片类型(canvas转的图片一般都是png,也可以指定其他类型)
let conversions = base64ToBlob(file, type); // 调用base64转图片方法
// conversions 就是转化之后的图片文件,
function base64ToBlob(urlData, type) {
let arr = urlData.split(',');
let mime = arr[0].match(/:(.*?);/)[1] || type;
// 去掉url的头,并转化为byte
let bytes = window.atob(arr[1]);
// 处理异常,将ascii码小于0的转换为大于0
let ab = new ArrayBuffer(bytes.length);
// 生成视图(直接针对内存):8位无符号整数,长度1个字节
let ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], {
type: mime
});
},