Fork me on GitHub

图片上传base64

图片上传base64

选择图片并转换

html 页面

1
2
3
4
5
<div id="divPreview">
<input id="iconPic1" name="iconPic" type="hidden"/>
<img id="imgHeadPhoto" src="" style="width: 120px; height: 130px; border: solid 1px #d2e2e2;" alt="" />
</div>
<input type="file" onchange="PreviewImage(this,'imgHeadPhoto','divPreview');" size="20" />

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//js本地图片预览,兼容ie[6-9]、火狐、Chrome17+、Opera11+、Maxthon3
function PreviewImage(fileObj, imgPreviewId, divPreviewId) {
//允许上传文件的后缀名
var allowExtention = ".jpg,.bmp,.gif,.png";
var extention = fileObj.value.substring(fileObj.value.lastIndexOf(".") + 1).toLowerCase();
var browserVersion = window.navigator.userAgent.toUpperCase();
if (allowExtention.indexOf(extention) > -1) {
//HTML5实现预览,兼容chrome、火狐7+等
if (fileObj.files) {
if (window.FileReader) {
var reader = new FileReader();
reader.onload = function (e) {
/*var pcBase64Text = e.target.result;
var blob = dataURLtoBlob(pcBase64Text);
console.log(e.target.result);*/
$("#iconPic1").val(e.target.result);
document.getElementById(imgPreviewId).setAttribute("src",e.target.result);
}
//读取文件把问价转换成 Base64 格式
reader.readAsDataURL(fileObj.files[0]);
}else if (browserVersion.indexOf("SAFARI") > -1) {
alert("不支持Safari6.0以下浏览器的图片预览!");
}
}else if (browserVersion.indexOf("MSIE") > -1) {
// 兼容 IE6 浏览器
if (browserVersion.indexOf("MSIE 6") > -1) {
document.getElementById(imgPreviewId).setAttribute("src", fileObj.value);
}else{ // 兼容 IE[7-9] 浏览器
fileObj.select();
if(browserVersion.indexOf("MSIE 9") > -1){
//不加上document.selection.createRange().text在ie9会拒绝访问
fileObj.blur();
}
var newPreview = document.getElementById(divPreviewId + "New");
if(newPreview == null){
newPreview = document.createElement("div");
newPreview.setAttribute("id", divPreviewId + "New");
newPreview.style.width = document.getElementById(imgPreviewId).width + "px";
newPreview.style.height =
document.getElementById(imgPreviewId).height + "px";
newPreview.style.height =
document.getElementById(imgPreviewId).height + "px";
}
newPreview.style.filter =
"progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='scale',
src='" + document.selection.createRange().text + "')";
var tempDivPreview = document.getElementById(divPreviewId);
tempDivPreview.parentNode.insertBefore(newPreview, tempDivPreview);
tempDivPreview.style.display = "none";
}
}else if (browserVersion.indexOf("FIREFOX") > -1) {
var firefoxVersion =
parseFloat(browserVersion.toLowerCase().match(/firefox\/([\d.]+)/)[1]);
//firefox7以下版本
if (firefoxVersion < 7) {
document.getElementById(imgPreviewId).
setAttribute("src", fileObj.files[0].getAsDataURL());
}else {//firefox7.0+
document.getElementById(imgPreviewId).
setAttribute("src", window.URL.createObjectURL(fileObj.files[0]));
}
}else {
document.getElementById(imgPreviewId).setAttribute("src", fileObj.value);
}
}else {
alert("仅支持" + allowExtention + "为后缀名的文件!");
fileObj.value = ""; //清空选中文件
if (browserVersion.indexOf("MSIE") > -1) {
fileObj.select();
document.selection.clear();
}
fileObj.outerHTML = fileObj.outerHTML;
}
return fileObj.value; //返回路径
}

这段代码里面我只用到 第一个判断 兼容chrome、火狐7+ ,使用文件内容改变事件。

结果

mark

关于 FileReader 的几种转化

因为我保存到数据的类型是 Clob ,所以我把 FileReader 解析的 Base64 内容直接以文本的形式保存到数据库。这样的好处是,在显示图片的时候直接给 img 标签的 src 赋值就好了,不用转。

假如你的图片要保存在类型是 Blob 的话,那就需要把图片转成二进制(原因,reader.readAsDataURL转化的是十六进制Blob 只能保存二进制内容)。下面的两个方法可以实现,Base64 转 二进制,二进制 转 Base64 。

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
function readBlobAsDataURL(blob, callback) {
var a = new FileReader();
a.onload = function(e) {callback(e.target.result);};
a.readAsDataURL(blob);
}
// 测试
readBlobAsDataURL(blob, function (dataurl){
console.log(dataurl);
});

存储图片到数据库

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.eyuninfo.bean.uomp.keeperManager;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.Lob;
import com.eyuninfo.bean.EntityBean;
/**
* @author: shenwenfang
* @CreateDate: 2018-06-25
*/
public class KeeperManage extends EntityBean {
private static final long serialVersionUID = 7125755338853860747L;
// 我想办code
private String code;
// 功能名称
private String name;
// 页面跳转路径
private String url;
// 渠道:1表示移动银行 2表示直销银行
private String channel;
// 状态:0:正常 1表示删除
private String status;
/**
* 存放图片base64
*/
@Lob
private String iconPic;
// 省略了 set 和 get 方法
}

注意:在保存 base64 的字段加上 JPA 的 @Lob 注解。假如在查询字段报转换错误的话。

service 层

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.eyuninfo.uomp.web.keepermanager.service;
import com.eyuninfo.bean.uomp.keeperManager.KeeperManage;
import com.github.pagehelper.PageInfo;
import java.util.List;
public interface IKeperDealManageService {
/**
* 添加
* @param bean
* @return
*/
int addKeperDealManage(KeeperManage bean) throws Exception;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.eyuninfo.uomp.web.keepermanager.service;
import com.github.pagehelper.PageInfo;
import com.eyuninfo.bean.uomp.keeperManager.KeeperManage;
import com.eyuninfo.framework.base.service.impl.BaseService;
import java.util.List;
import org.springframework.stereotype.Service;
@Service("keperDealManageService")
public class KeperDealManageService extends BaseService implements IKeperDealManageService {
@Override
public int addKeperDealManage(KeeperManage bean) {
return super.insert("addKeperDealManage", bean);
}
}

controller 层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.eyuninfo.uomp.web.keepermanager.controller;
import com.eyuninfo.bean.ResultBean;
import com.eyuninfo.bean.uomp.keeperManager.KeeperManage;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
@Controller
@RequestMapping(value = "/keperDealManage")
public class KeperDealManageController extends BaseController {
@Resource
private IKeperDealManageService keperDealManageService;
/**
* 添加
* @param locale
* @param bean
* @return
*/
@RequestMapping(value = "/addKeperDealManage", method = { RequestMethod.POST })
@ResponseBody
public ResultBean<KeeperManage> addKeperDealManage(Locale locale, @ModelAttribute("KeperDealManage") KeeperManage bean) {
ResultBean<KeeperManage> rb = new ResultBean<KeeperManage>();
try {
// 生成主键
bean.setCode(DateUtil.getCurDataFormat("yyyyMMddHHmmssSSS"));
String date = DateUtil.getCurDataFormat("yyyyMMddHHmmss");
bean.setCreatetime(date);
bean.setUpdateTime(date);
int newKey = keperDealManageService.addKeperDealManage(bean);
if(newKey > 0){
rb.setReturnCode(SysConstant.SYS_RETURN_SUCCESS_CODE);
rb.setReturnMessage(SysConstant.SYS_RETURN_SUCCESS_MESSAGE);
} else {
rb.setReturnCode(SysConstant.SYS_RETURN_FAILED_CODE);
rb.setReturnMessage(SysConstant.SYS_RETURN_FAILED_MESSAGE);
}
} catch (Exception e) {
e.printStackTrace();
log.error("异常:"+e.getMessage());
rb.setReturnCode(SysConstant.SYS_RETURN_EXCEPTION_CODE);
rb.setReturnMessage("异常:"+e.getMessage());
}
return rb;
}
}

XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eyuninfo.uomp.web.keepermanager.service.IKeperDealManageService">
insert into
keeper_deal_manage (
code,
name,
url,
channel,
creator,
createtime,
operator,
update_time,
sort,
icon_pic,
funtype
)
values (
#{code,jdbcType=VARCHAR},
#{name,jdbcType=VARCHAR},
#{url,jdbcType=VARCHAR},
#{channel,jdbcType=VARCHAR},
#{creator,jdbcType=VARCHAR},
#{createtime,jdbcType=VARCHAR},
#{operator,jdbcType=VARCHAR},
#{updateTime,jdbcType=VARCHAR},
#{sort,jdbcType=DECIMAL},
#{iconPic,jdbcType=CLOB},
#{funType,jdbcType=VARCHAR}
)
</mapper>

结果

mark

mark

保存的是一段很长得字符串(十六进制),把它放到浏览器的访问就是一张图片。

关联知识点

FileList 对象和 file 对象

HTML 中的 input[type=”file”] 标签有个 multiple 属性,允许用户选择多个文件,FileList对象则就是表示用户选择的文件列表。这个列表中的每一个文件,就是一个 file 对象。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
<input type="file" id="files" multiple>
<script>
var elem = document.getElementById('files');
elem.onchange = function (event) {
var files = event.target.files;
for (var i = 0; i < files.length; i++) {
// 文件类型为 image 并且文件大小小于 200kb
if(files[i].type.indexOf('image/') !== -1 && files[i].size < 204800){
console.log(files[i].name);
}
}
}
</script>

mark

input 中有个 accept 属性,可以用来规定能够通过文件上传进行提交的文件类型。

accept=”image/*” 可以用来限制只允许上传图像格式。但是在 Webkit 浏览器下却出现了响应滞慢的问题,要等上好几秒才弹出文件选择框。

解决方法就是将 * 通配符改为指定的 MIME 类型。

1
<input type="file" accept="image/gif,image/jpeg,image/jpg,image/png">

Blob 对象

Blob 对象相当于一个容器,可以用于存放二进制数据。它有两个属性,size 属性表示字节长度,type 属性表示 MIME 类型。

创建

1
var blob = new Blob(['hello'], {type:"text/plain"});

Blob 构造函数中的第一个参数是一个数组,可以存放 ArrayBuffer对象、ArrayBufferView 对象、Blob对象和字符串。

Blob 对象可以通过 slice() 方法来返回一个新的 Blob 对象。

1
var newblob = blob.slice(0,5, {type:"text/plain"});

slice() 方法使用三个参数,均为可选。第一个参数代表要从Blob对象中的二进制数据的起始位置开始复制,第二个参数代表复制的结束位置,第三个参数为 Blob 对象的 MIME 类型。

canvas.toBlob() 也可以创建 Blob 对象。toBlob() 使用三个参数,第一个为回调函数,第二个为图片类型,默认为 image/png,第三个为图片质量,值在0到1之间。

1
2
var canvas = document.getElementById('canvas');
canvas.toBlob(function(blob){ console.log(blob); }, "image/jpeg", 0.5);

下载

Blod 对象可以通过 window.URL 对象生成一个网络地址,结合 a 标签的 download 属性来实现下载文件功能。

比如把 canvas 下载为一个图片文件。

1
2
3
4
5
6
7
8
9
10
11
12
var canvas = document.getElementById('canvas');
canvas.toBlob(function(blob){
// 使用 createObjectURL 生成地址,格式为 blob:null/fd95b806-db11-4f98-b2ce-5eb16b38ba36
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.download = 'canvas';
a.href = url;
// 模拟a标签点击进行下载
a.click();
// 下载后告诉浏览器不再需要保持这个文件的引用了
URL.revokeObjectURL(url);
});
坚持原创技术分享,您的支持将鼓励我继续创作!