周嵐
摘要:基于傳統(tǒng)的HTML5多文件上傳采用FormData方式,將文件數(shù)據(jù)編譯成鍵值對(duì),用異步請(qǐng)求方式上傳文件,但是不同瀏覽器對(duì)FormData對(duì)象的支持情況并不容樂(lè)觀,導(dǎo)致不支持FormData的瀏覽器文件上傳失敗。該文針對(duì)瀏覽器不支持FormData對(duì)象操作,提出在基于瀏覽器客戶(hù)端對(duì)圖片進(jìn)行Base64編碼,將圖片轉(zhuǎn)換為字符串提交,在服務(wù)器端再對(duì)其進(jìn)行解碼后再生成圖片文件的通用圖片上傳方法。
關(guān)鍵詞:HTML5;FormData;Base64;文件上傳
中圖分類(lèi)號(hào):TP393? ? 文獻(xiàn)標(biāo)識(shí)碼:A? ? ? 文章編號(hào):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應(yīng)用開(kāi)發(fā)中的通用功能,傳統(tǒng)的圖片上傳通過(guò)表單選擇客戶(hù)端圖片,在提交表單時(shí)將圖片轉(zhuǎn)換為二進(jìn)制方式上傳到服務(wù)器。在HTML5標(biāo)準(zhǔn)中,增加了一個(gè)新的接口FormData,可以通過(guò)JavaScript采用鍵值對(duì)的方式來(lái)模擬表單控件,并可以通過(guò)異步方式提交,大大提高了用戶(hù)體驗(yàn)。目前大部分瀏覽器都能支持FormData對(duì)象,但是有的瀏覽器只部分支持FormData對(duì)象,比如蘋(píng)果系統(tǒng)的safari瀏覽器,在進(jìn)行圖片上傳時(shí)就不能采用FormData對(duì)象。而目前尤其是基于手機(jī)端圖片上傳的廣泛應(yīng)用,為了設(shè)計(jì)通用圖片上傳功能,就不能采用FormData對(duì)象,針對(duì)這種情況該文提出一種跨瀏覽器的多圖片上傳方法,在客戶(hù)端通過(guò)JavaScript對(duì)用戶(hù)選擇的圖片進(jìn)行Base64編碼,通過(guò)Post方式將編碼后的字符串發(fā)送到服務(wù)器端,然后在服務(wù)器端對(duì)字符串進(jìn)行Base64解碼,并生成圖片文件[1]。這種圖片上傳方法一方面兼容了瀏覽器,同時(shí)方便了用戶(hù)體驗(yàn)。
2 基于Base64編碼的圖片上傳方法簡(jiǎn)介
基于Base64編碼的圖片上傳方法,主要包括客戶(hù)端對(duì)圖片文件編碼,服務(wù)器端解碼并生成圖片文件兩個(gè)部分,如圖1所示。
當(dāng)用戶(hù)選擇要上傳的圖片后,先對(duì)圖片進(jìn)行壓縮,利用HTML5的canvas對(duì)象,重新繪制圖片,根據(jù)要求設(shè)置壓縮比例,重新生成新的圖片數(shù)據(jù),并對(duì)其進(jìn)行Base64編碼,將圖片文件的原始文件名和生成的Base64編碼保存到Json數(shù)據(jù)格式的對(duì)象數(shù)組中,最后上傳時(shí)只要將Json文件發(fā)送到服務(wù)器端即可。在服務(wù)器端,接收到客戶(hù)端請(qǐng)求的Json數(shù)據(jù)后,先對(duì)其進(jìn)行解析,分離出原文件名和圖片對(duì)應(yīng)的Base64編碼,并圖片數(shù)據(jù)進(jìn)行Base64解碼,重新生成新的圖片文件,并將新的文件名返回到客戶(hù)端。
3 基于Base64編碼的圖片上傳方法實(shí)現(xiàn)
基于Base64編碼的圖片上傳分為客戶(hù)端壓縮編碼和服務(wù)器端解碼生成新的圖片文件并返回客戶(hù)端新圖片的文件名。
3.1 客戶(hù)端圖片壓縮及編碼
當(dāng)用戶(hù)選擇完圖片后,通過(guò)調(diào)用ImageCompressor組件,首先對(duì)圖片進(jìn)行壓縮,圖片壓縮的質(zhì)量和生成圖片最大和最小尺寸自行設(shè)置,壓縮完成后使用HTML5的FileReader對(duì)象將圖片數(shù)據(jù)進(jìn)行Base64編碼,同時(shí)將圖片的文件名和生成的編碼保存到Json對(duì)象數(shù)組中[2],具體代碼如程序1所示。
function compress(files,num)
{
var flen=files.length;
if(num==files.length)
{
return;//沒(méi)有圖片了需要壓縮了
}
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);//臨時(shí)保存原始文件名
var fileReader = new FileReader();
fileReader.onload = function (e) {
var base64=e.target.result.replace(/^data:image\/(png|jpeg);base64,/,"")
//保存圖片數(shù)據(jù)到Json對(duì)象數(shù)組中
picarr.push({"filename":result.name,"base64":base64});
compress(files,num);//壓縮下一張圖片
}
fileReader.readAsDataURL(result);
},
error(e) {
console.log(e.message);
},
});
}
程序1? ?客戶(hù)端選擇圖片進(jìn)行壓縮及保存
當(dāng)所有圖片壓縮成功后,要上傳的圖片數(shù)據(jù)也保存到了Json對(duì)象數(shù)組中了,這時(shí)我們只需要將這個(gè)Json對(duì)象數(shù)組上傳到服務(wù)器端,同時(shí)在服務(wù)器上返回一個(gè)Json對(duì)象,包括圖片的原始文件名和新生成的文件名,具體實(shí)現(xiàn)如程序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];
}
}
}
//////////////保存數(shù)據(jù)
}
});
程序2? ?客戶(hù)端請(qǐng)求圖片數(shù)據(jù)
3.2 服務(wù)器端保存圖片
在服務(wù)器端,當(dāng)接收到客戶(hù)端的圖片數(shù)據(jù)請(qǐng)求后,先對(duì)Json對(duì)象進(jìn)行解析,取出圖片的Base64編碼,并對(duì)其進(jìn)行解碼生成圖片文件[3],具體實(shí)現(xiàn)如程序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("文件類(lèi)型不匹配");
}//生成新測(cè)文件名,采用時(shí)間戳方式
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格式到客戶(hù)端
程序3? ?服務(wù)器端對(duì)圖片數(shù)據(jù)進(jìn)行Base64解碼
在程序3中,對(duì)客戶(hù)端請(qǐng)求的每個(gè)圖片數(shù)據(jù)進(jìn)行Base64解碼,同時(shí)生成新的圖片文件保存到指定文件夾中,具體實(shí)現(xiàn)如程序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) {// 處理數(shù)據(jù)
if (b[i] < 0) {
b[i] += 256;
}
}
File tempFile = new File(path); //文件夾不存在則自動(dòng)創(chuàng)建
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? ?服務(wù)器端對(duì)圖片Base64解碼
當(dāng)服務(wù)器端處理圖像數(shù)據(jù)解碼時(shí),并將圖片的原始文件名和生成的新文件名保存到Map集合中,最后以Json格式返回到客戶(hù)端,便于客戶(hù)端獲取新生成的圖片名保存到數(shù)據(jù)庫(kù)中[4]。
4 結(jié)束語(yǔ)
該文針對(duì)HTML5中圖片上傳的兼容性,提出對(duì)客戶(hù)端圖片進(jìn)行Base64編碼為字符串方式提交,一方面彌補(bǔ)了瀏覽器對(duì)FormData對(duì)象不支持的缺陷,同時(shí)也滿(mǎn)足了動(dòng)態(tài)多圖片上傳的功能。并在實(shí)際移動(dòng)端得到了具體的應(yīng)用,在蘋(píng)果瀏覽器和谷歌平臺(tái)下面的瀏覽器均得到了驗(yàn)證,滿(mǎn)足了用戶(hù)圖片上傳通用性的要求。
參考文獻(xiàn):
[1] 劉耀欽. 利用HTML5拖放技術(shù)實(shí)現(xiàn)多文件異步上傳[J]. 四川理工學(xué)院學(xué)報(bào): 自然科學(xué)版, 2015(1): 1673-1549.
[2] 糜梅. 基于HTML5的文件上傳類(lèi)設(shè)計(jì)[J]. 電腦知識(shí)與技術(shù), 2015(2): 1009-3044.
[3] 王莉敏. 基于HTML5大文件斷點(diǎn)續(xù)傳的實(shí)現(xiàn)方案[J]. 計(jì)算機(jī)與現(xiàn)代化, 2016(3): 1006-2475.
[4] Joker_Ye. HTML5實(shí)現(xiàn)圖片壓縮上傳功能[EB/OL]. https://blog.csdn.net/hj7jay/article/details/51003926.