APP下载

一种基于Base64编码的多图片上传技术研究

2018-01-20周岚

电脑知识与技术 2018年31期

周岚

摘要:基于传统的HTML5多文件上传采用FormData方式,将文件数据编译成键值对,用异步请求方式上传文件,但是不同浏览器对FormData对象的支持情况并不容乐观,导致不支持FormData的浏览器文件上传失败。该文针对浏览器不支持FormData对象操作,提出在基于浏览器客户端对图片进行Base64编码,将图片转换为字符串提交,在服务器端再对其进行解码后再生成图片文件的通用图片上传方法。

关键词:HTML5;FormData;Base64;文件上传

中图分类号:TP393    文献标识码:A      文章编号:1009-3044(2018)31-0106-03

Research on Multi Image Uploading Technology Based on Base64 Encoding

ZHOU Lan

(Department of information technology, Xuzhou Vocational College of Finance and economics, Jiangsu, Xuzhou 221008,China)

Abstract: Based on the traditional HTML5 multi-file uploading method, the file data is compiled into key-value pairs and uploaded asynchronously. However, the support of different browsers for FormData objects is not optimistic, which leads to the failure of file uploading in browsers that do not support FormData. In view of the fact that browsers do not support the operation of FormData objects, this paper proposes a general image uploading method based on browser client to encode pictures by Base64, convert pictures to string submission, decode them on the server and regenerate them into picture files.

Key words: HTML5; FormData; Base64; file upload

1 背景

基于瀏览器的图片上传是Web应用开发中的通用功能,传统的图片上传通过表单选择客户端图片,在提交表单时将图片转换为二进制方式上传到服务器。在HTML5标准中,增加了一个新的接口FormData,可以通过JavaScript采用键值对的方式来模拟表单控件,并可以通过异步方式提交,大大提高了用户体验。目前大部分浏览器都能支持FormData对象,但是有的浏览器只部分支持FormData对象,比如苹果系统的safari浏览器,在进行图片上传时就不能采用FormData对象。而目前尤其是基于手机端图片上传的广泛应用,为了设计通用图片上传功能,就不能采用FormData对象,针对这种情况该文提出一种跨浏览器的多图片上传方法,在客户端通过JavaScript对用户选择的图片进行Base64编码,通过Post方式将编码后的字符串发送到服务器端,然后在服务器端对字符串进行Base64解码,并生成图片文件[1]。这种图片上传方法一方面兼容了浏览器,同时方便了用户体验。

2 基于Base64编码的图片上传方法简介

基于Base64编码的图片上传方法,主要包括客户端对图片文件编码,服务器端解码并生成图片文件两个部分,如图1所示。

当用户选择要上传的图片后,先对图片进行压缩,利用HTML5的canvas对象,重新绘制图片,根据要求设置压缩比例,重新生成新的图片数据,并对其进行Base64编码,将图片文件的原始文件名和生成的Base64编码保存到Json数据格式的对象数组中,最后上传时只要将Json文件发送到服务器端即可。在服务器端,接收到客户端请求的Json数据后,先对其进行解析,分离出原文件名和图片对应的Base64编码,并图片数据进行Base64解码,重新生成新的图片文件,并将新的文件名返回到客户端。

3 基于Base64编码的图片上传方法实现

基于Base64编码的图片上传分为客户端压缩编码和服务器端解码生成新的图片文件并返回客户端新图片的文件名。

3.1 客户端图片压缩及编码

当用户选择完图片后,通过调用ImageCompressor组件,首先对图片进行压缩,图片压缩的质量和生成图片最大和最小尺寸自行设置,压缩完成后使用HTML5的FileReader对象将图片数据进行Base64编码,同时将图片的文件名和生成的编码保存到Json对象数组中[2],具体代码如程序1所示。

function compress(files,num)

{

var flen=files.length;

if(num==files.length)

{

return;//没有图片了需要压缩了

}

new ImageCompressor(files[num], {

quality: .6,

maxWidth:1024,

maxHeight:1024,

minWidth:200,

minHeight:200,

success(result) {

var outputURL = window.URL.createObjectURL(result);

num++;

var objf={'id':index, 'value':outputURL ,'filename':result.name};

clientArr.push(objf);//临时保存原始文件名

var fileReader = new FileReader();

fileReader.onload = function (e) {

var base64=e.target.result.replace(/^data:image\/(png|jpeg);base64,/,"")

//保存图片数据到Json对象数组中

picarr.push({"filename":result.name,"base64":base64});

compress(files,num);//压缩下一张图片

}

fileReader.readAsDataURL(result);

},

error(e) {

console.log(e.message);

},

});

}

程序1   客户端选择图片进行压缩及保存

当所有图片压缩成功后,要上传的图片数据也保存到了Json对象数组中了,这时我们只需要将这个Json对象数组上传到服务器端,同时在服务器上返回一个Json对象,包括图片的原始文件名和新生成的文件名,具体实现如程序2所示。

$.ajax({

type:'post',

url:'/upload/multiPic',

data:JSON.stringify(picarr),

processData: false,

contentType: 'application/json',

success:function(res)

{

for(var key in res.data )

{

for(var i=0;i<contarr.length;i++)

{     if(contarr[i].filename==key)

{

clientArr[i].value=res.data[key];

}

}

}

//////////////保存數据

}

});

程序2   客户端请求图片数据

3.2 服务器端保存图片

在服务器端,当接收到客户端的图片数据请求后,先对Json对象进行解析,取出图片的Base64编码,并对其进行解码生成图片文件[3],具体实现如程序3所示。

ResultData rs=new ResultData();

JSONArray ls=JSON.parseArray(str);

if(ls.isEmpty())

throw new Exception("上传文件不能为空");

HashMap map=new HashMap();

for(int j=0;j<ls.size();j++)

{

JSONObject job = ls.getJSONObject(j);

String ofilename=job.getString("filename");

//原始文件名

String  type = ofilename.substring(ofilename.lastIndexO(".")); // 获取文件的后缀

if(!".png".equals(type.toLowerCase()) && !".jpg".equals(type.toLowerCase()) && !".gif".equals(type.toLowerCase()))

{

throw new Exception("文件类型不匹配");

}//生成新测文件名,采用时间戳方式

String webFilename=common.getCTime()+"_"+String.valueOf(j)+type;

String nfilename=fileRoot+"/"+webFilename;

String baseStr=job.getString("base64"); if(common.base64StrToImage(baseStr, nfilename))

{

map.put(ofilename,"/upload/"+common.getMonth()+"/"+webFilename);

}

else

rs.setFaild(0,"error trans", null);

}

rs.setSuccess(1, "success",map);

}catch(Exception e){

e.printStackTrace();

}

renderJson(rs);//渲染Json格式到客户端

程序3   服务器端对图片数据进行Base64解码

在程序3中,对客户端请求的每个图片数据进行Base64解码,同时生成新的图片文件保存到指定文件夹中,具体实现如程序4所示。

public static boolean base64StrToImage(String imgStr, String path) {

if (imgStr == null)

return false;

Base64.Decoder decoder = Base64.getDecoder();

try {// 解密

byte[] b = decoder.decode(imgStr);

for (int i = 0; i < b.length; ++i) {// 处理数据

if (b[i] < 0) {

b[i] += 256;

}

}

File tempFile = new File(path); //文件夹不存在则自动创建

if (!tempFile.getParentFile().exists()) {

tempFile.getParentFile().mkdirs();

}

OutputStream out = new FileOutputStream(tempFile);

out.write(b);

out.flush();

out.close();

return true;

} catch (Exception e) {

return false;

}}

程序4   服務器端对图片Base64解码

当服务器端处理图像数据解码时,并将图片的原始文件名和生成的新文件名保存到Map集合中,最后以Json格式返回到客户端,便于客户端获取新生成的图片名保存到数据库中[4]。

4 结束语

该文针对HTML5中图片上传的兼容性,提出对客户端图片进行Base64编码为字符串方式提交,一方面弥补了浏览器对FormData对象不支持的缺陷,同时也满足了动态多图片上传的功能。并在实际移动端得到了具体的应用,在苹果浏览器和谷歌平台下面的浏览器均得到了验证,满足了用户图片上传通用性的要求。

参考文献:

[1] 刘耀钦. 利用HTML5拖放技术实现多文件异步上传[J]. 四川理工学院学报: 自然科学版, 2015(1): 1673-1549.

[2] 糜梅. 基于HTML5的文件上传类设计[J]. 电脑知识与技术, 2015(2): 1009-3044.

[3] 王莉敏. 基于HTML5大文件断点续传的实现方案[J]. 计算机与现代化, 2016(3): 1006-2475.

[4] Joker_Ye. HTML5实现图片压缩上传功能[EB/OL]. https://blog.csdn.net/hj7jay/article/details/51003926.