0%

php base64形式图片处理,保存到文件以及插件介绍

网页上有些图片的src或者css背景图片都是后面跟了一大串字符串,比如:

1
2
3
4
5
6
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJAQMAAADaX 
5RTAAAAA3NCSVQICAjb4U/gAAAABlBMVEX///+ZmZmOUEqyAAAAAnRSTlMA/1uR
IrUAAAAJcEhZcwAACusAAArrAYKLDVoAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDk
vMjAvMTIGkKG+AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26L
yyjAAAAB1JREFUCJljONjA8LiBoZyBwY6BQQZMAtlAkYMNAF1fBs/zPvcnAAAAA
ElFTkSuQmCC ....

Data URI scheme是在RFC2397中定义的,目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入。比如上面那串字符,其实是一张小图片,将这些字符复制黏贴到火狐的地址栏中并转到,就能看到它了,一张1X36的白灰png图片。

在上面的Data URI中,data表示取得数据的协定名称,image/png 是数据类型名称,base64 是数据的编码方法,逗号后面就是这个image/png文件base64编码后的数据。

目前,Data URI scheme支持的类型有:
data:,文本数据
data:text/plain,文本数据
data:text/html,HTML代码
data:text/html;base64,base64编码的HTML代码
data:text/css,CSS代码
data:text/css;base64,base64编码的CSS代码
data:text/javascript,Javascript代码
data:text/javascript;base64,base64编码的Javascript代码
data:image/gif;base64,base64编码的gif图片数据
data:image/png;base64,base64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据

目前,IE8、Firfox、Chrome、Opera浏览器都支持这种小文件嵌入。

以下是php处理实战:

插件准备

插件地址:https://www.jq22.com/jquery-info18454
如果地址失效可以根据下面操作:

插件渲染

资源准备:

1
2
<script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>
<script type="text/javascript" src="imgFileupload.js"></script>

html和css:

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
<style>
.box{
margin: 50px auto;
}
.imgFileUploade{
width: 100%;padding: 10px;
}
.imgFileUploade .header{
height: 50px;width: 100%;line-height:50px;
}
.imgFileUploade .header span{
display: block;float:left;
}
.imgFileUploade .header span.imgTitle{
line-height:50px;
}
.imgFileUploade .header span.imgTitle b{
color:red;margin:0 5px;line-height: 57px;display: block;float: right;font-size: 20px;
}
.imgFileUploade .header span.imgClick{
width: 50px;height: 50px;margin-left: 10px;cursor: pointer;
background: url(/libs/img-file-update/img/addUpload.png) no-repeat center center;background-size:cover;
background-size: 40px 40px;
}
.imgFileUploade .header span.imgcontent{
color:#999;margin-left:120px;line-height: 50px;
}
.imgFileUploade .imgAll{
width: 100%; margin-top: 5px;
}
.imgFileUploade .imgAll ul:after{
visibility: hidden; display: block; font-size: 0; content: "."; clear: both; height: 0
}
.imgFileUploade .imgAll li{
width: 100px;height: 100px;border:solid 1px #ccc;margin:8px 5px;float: left;position: relative;box-shadow: 0 0 10px #eee;
}
.imgFileUploade .imgAll li img{
position: absolute;top:0;left:0;width: 100%;height: 100%;display: block;
}
.delImg{
position: absolute;top:-10px;right:-7px;width: 22px;height: 22px;background: #000;border-radius: 50%;display: block;text-align: center;line-height: 22px;color:#fff;font-weight: 700;font-style:normal;cursor: pointer;
}
.box,.box2,.box3,.box4{
border:solid 1px #ccc;
}
</style>

<dl class="zs_f">
<dt>图片信息:</dt>
<div class="box"></div> <!-- box为插件容器 -->
</dl>

js

1
2
3
4
5
6
7
8
9
10
11
// 图片上传插件加载 初始化
var imgFile = new ImgUploadeFiles('.box',function(e){
this.init({
MAX : 10, //限制上传个数
MH : 2200, //像素限制高度
MW : 2000, //像素限制宽度
callback : function(arr){
console.log(arr)
}
});
});

imgFileupload.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
~(function(win){
var htmls = '<input type="file" name="" id="" class="imgFiles" style="display: none" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg" multiple>'+
'<div class="header">'+
' <span class="imgTitle">'+
' 点击添加'+
' </span>'+
' <span class="imgClick">'+
' </span>'+
' <span class="imgcontent">'+
' 请上传'+
' </span>'+
'</div>'+
'<div class="imgAll">'+
' <ul>'+
' </ul>'+
'</div>';
var ImgUploadeFiles = function(obj,fn){
var _this = this;
this.bom = document.querySelector(obj);

if(fn) fn.call(_this);
this.ready();

};
ImgUploadeFiles.prototype = {
init : function(o){
this.MAX = o.MAX || 5;
this.callback = o.callback;
this.MW = o.MW || 10000;
this.MH = o.MH || 10000;
},
ready : function(){
var _self = this;
this.dom = document.createElement('div');
this.dom.className = 'imgFileUploade';
this.dom.innerHTML = htmls;
this.bom.appendChild(this.dom);
this.files = this.bom.querySelector('.imgFiles');
this.fileClick = this.bom.querySelector('.imgClick');
this.fileBtn(this.fileClick,this.files);
this.imgcontent = this.bom.querySelector('.imgcontent');
this.imgcontent.innerHTML = '限制上传 <b style="color:red">'+this.MAX+'</b>张 '+_self.MW+' * '+_self.MH+'像素的图片';

},
fileBtn : function(c,f){
var _self = this;
var _imgAll = $(c).parent().parent().find('.imgAll ul');
$(c).off().on('click',function(){
$(f).click();

$(f).off().on('change',function(){
var _this = this;
_private.startUploadImg(_imgAll,_this.files,_self.MAX,_self.callback,_self.MW,_self.MH);
});
});
}
};
var _dataArr = [];
var _private = {
startUploadImg : function(o,files,MAX,callback,W,H){
_dataArr.length = 0;
var _this = this;
var fileImgArr = [];

if(files.length > MAX ){
alert('不能大于'+MAX+'张');
return false;
};
var lens = $(o).find('li').length ;
if(lens >= MAX ){
alert('不能大于'+MAX+'张');
return false;
};

for(var i=0,file;file=files[i++];){

var reader = new FileReader();
reader.onload = (function(file){
return function(ev){
var image = new Image();
image.onload=function(){
var width = image.width;
var height = image.height;

fileImgArr.push({
fileSrc : ev.target.result,
fileName : file.name,
fileSize : file.size,
height : height,
width : width
});
};
image.src= ev.target.result;


};
})(file);
reader.readAsDataURL(file);
}
//创建分时函数
var imgTimeSlice = _this.timeChunk(fileImgArr,function(file){
if(file.width > W || file.height > H){
alert('图片不能大于'+W+'*'+H+'像素');
return false;
}
//调用图片类
var up = new ImgFileupload(o,file.fileName,file.fileSrc,file.fileSize,callback);
up.init();
},1);
imgTimeSlice(); //调用分时函数
},
timeChunk : function(arr, fn, count) {
var obj, t;
var len = arr.length;
var start = function() {
for (var i = 0; i < Math.min(count || 1, arr.length); i++) {
var obj = arr.shift();
fn(obj)
}
};
return function() {
t = setInterval(function() {
if (arr.length === 0) {
return clearInterval(t);
}
start();
},200)
}
}
};

var ImgFileupload = function(b,imgName,imgSrc,imgSize,callback){
this.b = b;
this.imgName = imgName;
this.imgSize = imgSize;
this.imgSrc = imgSrc;
this.callback = callback;
};
var _delId = 1; //删除id用于判断删除个数
ImgFileupload.prototype.init =function() {
_delId++;
var _self = this;
this.dom = document.createElement('li');
this.dom.innerHTML =
' <img src="/libs/img-file-update/img/login.gif" alt="" data-src="'+this.imgSrc +'" class="imsg">'+
' <i class="delImg">'+
' X'+
' </i>';
$(this.dom).attr({'data-delId':_delId,'data-delName':this.imgName});
$(this.b).append(this.dom);
var _Img = new Image();
_Img.src = $(this.dom).find('img').attr('data-src');
_Img.onload = function(){
$(_self.dom).find('img').attr('src',_Img.src);
}
_dataArr.push({'delId' :_delId,src : this.imgSrc});
_self.callback(_dataArr);
// $(this.b).parent().parent().parent().attr('data-dataImgs',JSON.stringify(_dataArr));
var _delAll = $(this.b).find('.delImg');
for(var i=0;i<_delAll.length;i++){
$(_delAll[i]).off().on('click',function(){
$(this).parent().fadeOut('slow',function(){
$(this).remove();
});
var _deid = $(this).parent().attr('data-delId');
for(var n=0;n<_dataArr.length;n++){
if(_dataArr[n].delId == _deid){
_dataArr.splice(n,1);
}
}
_self.callback(_dataArr)
// $(this.b).parent().parent().parent().attr('data-dataImgs',JSON.stringify(_dataArr))

});
};
var _Imgpreview = $(this.b).find('img');
for(var k=0;k<_Imgpreview.length; k++){
$(_Imgpreview[k]).off().on('click',function(){
console.log($(this).attr('src'))
})
}

}

win.ImgUploadeFiles = ImgUploadeFiles;
})(window);

页面渲染效果:
pic
pic

上图能够看到,这个插件所加载的图片资源就是存储在浏览器上面的资源,也就是上面所说的base64的方式,那么后端如何来解析又怎么保存图片到本地呢?

后端处理 - php

前端在传输图片信息的时候就需要把这个带data:image/jpeg;base64./…这个数据传递到后端,由后端来解析;

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
/**
* - 将Base64图片转换为本地图片并保存
*
* @param $base64_image_content_list
* @param $path //路径
* @return array|bool
*/
function base64_image_content($base64_image_content_list, $path)
{
$upload_img_name = [];
$error_data = [];
$file_path = '/data/htdocs/psi.a.hongju.cc/public'.$path; // 拼接成绝对路径,这里必须要绝对路径
try {
foreach ($base64_image_content_list as $base64_image_content) {
//匹配出图片的格式
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)) {
$type = $result[2];
$new_file = $file_path . "/" . date('Ymd', time()) . "/";
if (!file_exists($new_file)) {
//检查是否有该文件夹,如果没有就创建,并给予最高权限
mkdir($new_file); // 规定权限。默认是 0777。
}
// 重新命名
$new_file = $new_file . time().mt_rand(100,999). ".{$type}";

// 写入文件夹 执行文件的写入
if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))) {
$upload_img_name[] = $new_file;
}
} else {
$error_data[] = $base64_image_content;
}
}
}catch (Exception $e) {
$error_data[] = $base64_image_content;
}
if (!empty($error_data)) {
return [];
}
if (!empty($upload_img_name)) {
return $upload_img_name;
}
}

上面的方法是批量处理的,其中的mkdir地方在创建文件夹的时候,特别注意服务器上面的文件权限问题,不然创建文件夹不成功,其次$file_path参数必须为绝对路径(我没太明白,就这么用吧)
我给的$path = ‘/upload/abnormal’;

上传后效果:
pic

总结

1、这种资源是存储在浏览器上面的;
2、利用上诉js插件可以模拟这个场景;
3、注意避坑的地方;