前言:最近公司的項目在作全網營銷,要作非微信瀏覽器的wap 站 的改版,其中涉及到的一點技術就是採用H5 選擇手機相冊中的圖片,或者拍照,再將獲取的圖片進行壓縮以後上傳。javascript
這個功能模塊主要有這5點比較難:css
1手機獲取相冊的圖片文件,拍照的圖片文件,經過js 的自帶的img對象,獲取圖片對象。 html
2.圖片的壓縮,採用canvas 畫布進行壓縮圖片,圖片的質量經過參數指定大小,數值區間在0.1-0.9之間,數值越小壓縮的比例越小java
3.圖片的預覽,將canvas畫布生成的圖片通過旋轉平移到預覽區域jquery
4.圖片的刪除和上傳android
5.圖片的存儲ios
(一):h5 獲取手機的圖片web
這是圖片上傳的頁面,其中包含了:預覽大圖的插件smartphoto,修正ios獲取圖片旋轉的插件,正在加載中效果的插件。(由於項目的框架使用的sgform js 提交表單,也能夠用本身的form 表單提交)ajax
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript"> var _speedMark = new Date(); </script> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <meta content="" name="keywords"/> <meta content="" name="description"/> <title>上傳圖片頁面</title> <link rel="stylesheet" type="text/css" href="/css/healthRecords.css" /> <!-- 查看大圖的css --> <link rel="stylesheet" href="/css/smartphoto.css" /> <!-- 查看大圖的js --> <script type="text/javascript" src="/js/jquery-smartphoto.min.js" ></script> <script src="/js/bootstrap.min.js" type="text/javascript" charset="utf-8"></script> <!-- form 表單提交 --> <script type="text/javascript" src="/js/jquery.sgfmform.js"></script> <!-- 引用核心層插件 --> <script type="text/javascript" src="/js/zyFile.js"></script> <!-- 引用控制層插件 --> <script type="text/javascript" src="/js/zyUpload.js"></script> <!-- 修正ios圖片旋轉 --> <script type="text/javascript" src="/js/exif.js"></script> <!-- 圖片正在加載中效果 --> <link rel="stylesheet" type="text/css" href="/css/loading/load.css" media="all"> <script type="text/javascript" src="/css/loading/load-min.js"></script> </head> <body> <body > <!-- form 表單須要提交的數據,能夠包含基本數據,和圖片數據 --> <form id="addExmInfo" method="post" enctype="application/x-www-form-urlencoded"> <div class="main" style="margin-bottom: 0;padding-bottom: 0;"> <ul class="write"> <li class="clearfix" onclick="openCalendar();"> <span>提交人姓名</span> <img src="/images/main-right.png" /> <input style="display:block;" value="" id="chooseDate" name="tijianTime" onfocus="this.blur()"> </li> </ul> </div> <div class="main" id="imageMain" style="border-bottom: 50px solid #f7f9fa;"> <div class="uploading" style="margin-top: 0;" id="uploadbtn" > <img src="/images/Upload_pic_icon.png" /> <p class="uploadingTop">上傳報告圖片(手機上傳)</p> <p class="uploadingBottom">注:請確保圖片上文字清晰可見</p> </div> <!-- 圖片預覽區 --> <div id="wx_chooseimg" class="imgView"></div> </div> <!-- 瀏覽器類型:微信瀏覽器或者非微信瀏覽器 --> <input value="" type="hidden" id="agentType" name="agentType"/> <!-- 刪除的圖片id --> <input type="hidden" id="delIds" name="delIds"/> <input type="button" id="submitButton" value="保存" class="btn btn-block main-btn save" /> </form> <!-- 真正觸發獲取手機相冊的元素 --> <input id="fileImage" style="display:none;" type="file" accept="image/*" size="30" name="imgSelected" multiple> <input id="state" type="hidden" /> <!-- 圖片加載中效果 --> <div id="test_mask_2" class="test_mask"></div> </body> <script type="text/javascript"> $(document).ready(function () { // 初始化圖片插件 $("#addExmInfo").zyUpload({ width : "1000px", // 寬度 height : "500px", // 寬度 itemWidth : "120px", // 文件項的寬度 itemHeight : "100px", // 文件項的高度 url : "/core/recordExplain.upReportInfoWeb.do", // 上傳文件的路徑 multiple : true, // 是否能夠多個文件上傳 dragDrop : true, // 是否能夠拖動上傳文件 del : true, // 是否能夠刪除文件 finishDel : false, // 是否在上傳文件完成後刪除預覽 /* 外部得到的回調接口 */ onSelect: function(files, allFiles){ // 選擇文件的回調方法 }, onDelete: function(file, surplusFiles){ // 刪除一個文件的回調方法 console.info(file); }, onSuccess: function(file){ // 文件上傳成功的回調方法 }, onFailure: function(file){ // 文件上傳失敗的回調方法 }, onComplete: function(responseInfo){ // 上傳完成的回調方法 } }); $(".img_viwer").smartPhoto({ resizeStyle: 'fit' }); /* 這是form表單提交的js ,直接用form表單提交,不用這個js也可 */ $("#addExmInfo").sgfmform({ ajaxurl : "/core/recordExplain.upReportInfoWeb.do", tiptype : 1, submittype : 2, callback : function(data,url){ if(data.returncode == 0){ alert("圖片上傳成功"); }else{ alert("圖片上傳失敗"); } $("#submitButton").attr('disabled',false); $("#submitButton").css("background-color","#05A3FF"); } }); }); /* 圖片刪除綁定點擊事件 */ function funBindDelEvent(index) { if ($(".file_del").length > 0) { confirmMsg("確認刪除圖片?",function(){ ZYFILE.funDeleteFile(parseInt(index), true); }); } }; /* 圖片正在加載中 */ function mask_element_continuious() { $.mask_element('#test_mask_2',3000); } </script> </html>
(二)兩個核心的圖片上傳的js數據庫
zyFile.js 這個js 包含圖片文件的獲取,圖片的上傳
/* * */ var ZYFILE = { fileInput : "#fileImage", // 選擇文件按鈕dom對象 uploadInput : $("#submitButton").get(0), // 上傳文件按鈕dom對象 dragDrop: null, //拖拽敏感區域 url : null, // 上傳action路徑 uploadFile : [], // 須要上傳的文件數組 lastUploadFile : [], // 上一次選擇的文件數組,方便繼續上傳使用 perUploadFile : [], // 存放永久的文件數組,方便刪除使用 fileNum : 0, // 表明文件總個數,由於涉及到繼續添加,因此下一次添加須要在它的基礎上添加索引 /* 提供給外部的接口 */ filterFile : function(files){ // 提供給外部的過濾文件格式等的接口,外部須要把過濾後的文件返回 }, onDelete : function(file, files){ // 提供給外部獲取刪除的單個文件,供外部實現刪除效果 file:當前刪除的文件 files:刪除以後的文件 }, onProgress : function(file, loaded, total){ // 提供給外部獲取單個文件的上傳進度,供外部實現上傳進度效果 }, onSuccess : function(file, responseInfo){ // 提供給外部獲取單個文件上傳成功,供外部實現成功效果 }, onFailure : function(file, responseInfo){ // 提供給外部獲取單個文件上傳失敗,供外部實現失敗效果 }, onComplete : function(responseInfo){ // 提供給外部獲取所有文件上傳完成,供外部實現完成效果 }, // 3.將獲取的圖片數據加入到文件數組中,注意下面的else 的判斷,這個判斷是由於ios 拍照每次獲取的圖片名稱都是同樣的,若是根據圖片名稱來區分是不是同一張圖片將會失敗。相同的圖片名稱只會顯示一張,因此這裏else 解決了ios 拍照不能拍屢次的問題 funGetFiles : function(e){ var self = this; /* 從事件中獲取選中的全部文件*/ var files = e.target.files || e.dataTransfer.files; self.lastUploadFile = this.uploadFile; this.uploadFile = this.uploadFile.concat(this.filterFile(files)); //將過濾後的文件從新組裝 var tmpFiles = []; /*由於jquery的inArray方法沒法對object數組進行判斷是否存在於,因此只能提取名稱進行判斷*/ var lArr = []; // 以前文件的名稱數組 var uArr = []; // 如今文件的名稱數組 $.each(self.lastUploadFile, function(k, v){ lArr.push(v.name); }); $.each(self.uploadFile, function(k, v){ uArr.push(v.name); }); $.each(uArr, function(k, v){ // 得到當前選擇的每個文件 判斷當前這一個文件是否存在於以前的文件當中 if($.inArray(v, lArr) < 0){ // 不存在 tmpFiles.push(self.uploadFile[k]); }else{ /* * 功能:由於ios每次拍照返回的文件名稱都是image.jpg 因此只用文件名去重的方式會致使大於第二次的拍照的圖片不能存放到uploadFile 數組中, * 預覽的時候就是沒有第二次及以上的拍照的圖片 * return:拍照的照片文件 */ if((v=="image.jpg")&&(k==(uArr.length-1))){ tmpFiles.push(self.uploadFile[k]); } } }); this.uploadFile = tmpFiles; // 調用對文件處理的方法 this.funDealtFiles(); return true; }, // 處理過濾後的文件,給每一個文件設置下標 funDealtFiles : function(){ var self = this; // 目前是遍歷全部的文件,給每一個文件增長惟一索引值 $.each(this.uploadFile, function(k, v){ // 由於涉及到繼續添加,因此下一次添加須要在總個數的基礎上添加 v.index = self.fileNum; // 添加一個以後自增 self.fileNum++; }); // 先把當前選中的文件保存備份 var selectFile = this.uploadFile; // 要把所有的文件都保存下來,由於刪除所使用的下標是全局的變量 this.perUploadFile = this.perUploadFile.concat(this.uploadFile); // 合併下上傳的文件 this.uploadFile = this.lastUploadFile.concat(this.uploadFile); // 4.這裏調用下面zyUpload.js 的onselect 方法,對圖片進行處理 this.onSelect(selectFile, this.uploadFile); return this; }, // 處理須要刪除的文件 isCb表明是否回調onDelete方法 // 由於上傳完成並不但願在頁面上刪除div,可是單獨點擊刪除的時候須要刪除div 因此用isCb作判斷 funDeleteFile : function(delFileIndex, isCb){ var self = this; // 在each中this指向沒個v 因此先將this保留 var tmpFile = []; // 用來替換的文件數組 // 合併下上傳的文件 var delFile = this.perUploadFile[delFileIndex]; // 目前是遍歷全部的文件,對比每一個文件 刪除 $.each(this.uploadFile, function(k, v){ if(delFile != v){ // 若是不是刪除的那個文件 就放到臨時數組中 tmpFile.push(v); }else{ } }); this.uploadFile = tmpFile; if(isCb){ // 執行回調 // 回調刪除方法,供外部進行刪除效果的實現 self.onDelete(delFile, this.uploadFile); } return true; }, // 11.圖片上傳的方法 funUploadFiles : function(){ if((ZYFILE.funReturnNeedFiles().length == 0)&&($("#wx_chooseimg:has(img)" ).length==0)){ alertMsg({"type" : 3, "content" : "請上傳圖片", "close" : true, "timeout" : 3000}, function(){}); }else{ //點擊保存以後按鈕灰掉 $("#submitButton").css("background-color","gray"); $("#submitButton").attr('disabled',true); $("#addExmInfo").submit(); } }, // 返回須要上傳的文件 funReturnNeedFiles : function(){ return this.uploadFile; }, // 初始化 init : function(){ // 初始化方法,在此給選擇、上傳按鈕綁定事件 var self = this; // 克隆一個自身 this.userAgent(); // 給元素添加屬性 // 1.點擊選擇圖片按鈕會先觸發這裏的監聽,點擊獲取圖片將從這裏開始 if(self.fileInput){ this.fileInput.addEventListener("change", function(e) {
2.將獲取的file文件交個funGetFileses(e)這個方法進行下一步的處理,e 包含獲取的圖片信息和其餘數據 self.funGetFiles(e); }, false); } }, /*判斷是android 仍是 ios android 要加capture="camera" ios 不用加 ; 1 表明android 2 表明ios*/ userAgent:function(){ var agentFlag=1; var u = navigator.userAgent; var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android終端 var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端 if(isAndroid){ //$(this.fileInput).attr("capture","camera"); $("#agentType").val("isAndroid") }else if(isiOS){ agentFlag=2; $("#agentType").val("isIos") }else{ } var ua = window.navigator.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) == 'micromessenger') { //alert("微信"); } else { // alert("非微信"); } return agentFlag; } };
zyUpload.js 這個js是圖片預覽,壓縮的核心js,首先要整理出這個js 的邏輯比較有點困難,對於那些在js 面向對象編程方面瞭解很少的童鞋,不過也沒多大問題多看幾遍就知道了。
這個js 首先要知道這幾點:
1.$.fn 這個的意思,這是jquery 的擴展方法,當給jquery 添加這個擴展方法的時候就可使用$操做符對這個js 的方法進行調用。
2. js 的函數回調,函數回調分爲同步回到和異步回調
3.returnthis.each(fucntion(){}) 這個的方法的做用是爲了鏈式操做
4. para = $.extend(defaults, options); 這個方法是加強,就是將默認的和特定的參數進行結合,能夠理解爲韋恩圖中的並集
/* 代碼整理:懶人之家 www.lanrenzhijia.com */ (function($, undefined) { $.fn.zyUpload = function(options, param) { return this.each(function() { var para = {}; // 保留參數 var self = this; // 保存組件對象 var base64Img = []; // 建立一個數組保存base64 編碼的圖片 var defaults = { width : "700px", // 寬度 height : "400px", // 寬度 itemWidth : "140px", // 文件項的寬度 itemHeight : "120px", // 文件項的高度 multiple : true, // 是否能夠多個文件上傳 dragDrop : true, // 是否能夠拖動上傳文件 del : true, // 是否能夠刪除文件 finishDel : false, // 是否在上傳文件完成後刪除預覽 minLimitNum : 2 * 1024 * 1024, // 當文件的大小小於這個值時,不壓縮 // 單位(bit) isResize : true, // 是否壓縮文件 base64ImgUrl : [], // 通過canvas 壓縮過的圖片地址,組成的圖片數組 /* 提供給外部的接口方法 */ onSelect : function(selectFiles, files) { },// 選擇文件的回調方法 selectFile:當前選中的文件 allFiles:還沒上傳的所有文件 onDelete : function(file, files) { }, // 刪除一個文件的回調方法 file:當前刪除的文件 files:刪除以後的文件 onSuccess : function(file) { }, // 文件上傳成功的回調方法 onFailure : function(file) { }, // 文件上傳失敗的回調方法 onComplete : function(responseInfo) { }, // 上傳完成的回調方法 }; para = $.extend(defaults, options); this.init = function() { this.addEvent(); this.createCorePlug(); // 調用核心js }; /** * 識別是不是手機瀏覽器 對選擇文件夾按鈕添加屬性 */ this.findIsPhone = function() { var userAgentInfo = navigator.userAgent; }; /* * 點擊圖片進行預覽 */ this.zoomOutImage = function(imgUrl) { }; /** * 功能:顯示統計信息和綁定繼續上傳和上傳按鈕的點擊事件 參數: 無 返回: 無 */ this.funSetStatusInfo = function(files) { var size = 0; var num = files.length; $.each(files, function(k, v) { // 計算獲得文件總大小 size += v.size; }); // 轉化爲kb和MB格式。文件的名字、大小、類型都是能夠現實出來。 if (size > 1024 * 1024) { size = (Math.round(size * 100 / (1024 * 1024)) / 100) .toString() + 'MB'; } else { size = (Math.round(size * 100 / 1024) / 100) .toString() + 'KB'; } alert("獲取圖片的總大小=="+size )
}; /** * 功能:過濾上傳的文件格式 參數: files 本次選擇的文件 返回: 經過的文件 */ this.funFilterEligibleFile = function(files) { var arrFiles = []; // 替換的文件數組 for (var i = 0, file; file = files[i]; i++) { if (file.size >= 51200000) { alert('您選擇的"' + file.name + '"圖片大小過大'); } else { // 在這裏須要判斷當前全部文件中 var fileExt = file.name.substr( file.name.lastIndexOf(".")).toLowerCase();// 得到文件後綴名 if (fileExt == ".png" || fileExt == ".gif" || fileExt == ".jpg" || fileExt == ".jpeg") {arrFiles.push(file);// 若是文件是圖片格式,那麼就放入文件的數組 } else { alert("您上傳的圖片格式不正確,請從新選擇!"); } } } return arrFiles; }; /* * 功能:對圖片進行壓縮 * 參數:img 是從文件系統中獲取的image對象 * max_width 預覽的最大寬度, * max_height 預覽的最大高度 * 返回值: src 須要填充的地址 */ function resizeMe(img, max_width, max_height) { // 獲取照片的拍攝方向 var orient = getPhotoOrientation(img); //當檢測圖片的方向爲6 的時候說明圖片方向右(exif.js 這麼定義的),開始旋轉圖片 if (orient == 6) { var canvas = document.createElement('canvas'); var width = img.width; var height = img.height; var exWith; var exHeight; canvas.width = height; canvas.height = width; var ctx = canvas.getContext("2d"); ctx.save();//保存狀態 ctx.rotate(90 * Math.PI / 180);//把畫布旋轉90度 //ctx.translate(0, height); //平移 // 執行Canvas的drawImage語句 ctx.drawImage(img, 0, -height, width,height);//把圖片繪製在畫布, //alert(getRatio(img)) ctx.restore();//恢復狀態 return canvas.toDataURL("image/jpeg", 0.1); } else { var canvas = document.createElement('canvas'); var width = img.width; var height = img.height; canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, width, height); //alert("比例=="+getRatio(img)); return canvas.toDataURL("image/jpeg", 0.2); } }; function getRatio(img) { alert("kaishi") /* if(/png$/i.test(img.src)) { alert(2); return 1; }*/ var iw = img.naturalWidth, ih = img.naturalHeight; var canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = ih; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); var data = ctx.getImageData(0, 0, 1, ih).data; var sy = 0; var ey = ih; var py = ih; while (py > sy) { var alpha = data[(py - 1) * 4 + 3]; if (alpha === 0) { ey = py; } else { sy = py; } py = (ey + sy) >> 1; } var ratio = (py / ih); return (ratio===0)?1:ratio; } /* * 功能:獲取照片的元信息(拍攝方向,來自exif.js 的api) * 返回值:方向的枚舉值 6 表明ios 返回的圖片方向 */ function getPhotoOrientation(img) { var orient; EXIF.getData(img, function() { orient = EXIF.getTag(this, 'Orientation'); }); return orient; } /** * 功能: 處理參數和格式上的預覽html 參數: files 本次選擇的文件 返回: 預覽的html */ this.funDisposePreviewHtml = function(file, img) { /* alert(img.substring((img.length-100),img.length)); */ var html = ""; // 處理不一樣類型文件表明的圖標 var fileImgSrc = "control/images/fileType/"; if (file.type.indexOf("rar") > 0) { fileImgSrc = fileImgSrc + "rar.png"; } else if (file.type.indexOf("zip") > 0) { fileImgSrc = fileImgSrc + "zip.png"; } else if (file.type.indexOf("text") > 0) { fileImgSrc = fileImgSrc + "txt.png"; } else { fileImgSrc = fileImgSrc + "file.png"; } var tempImgUrl=img.replace("data:image/jpeg;base64,", ""); var html = "<i class='rev' id='uploadList_"+file.index+"'>" ; // html += "<a class='img_viwer' data-caption='"+file.index+"' data-id='"+file.index+"' data-group='0' href='"+img+"'>" ; html += "<img id='uploadImage_" + file.index + "' src='"+img+"' class='uploadingImg' />" ; // html += "</a>"; html += "<img id='deleteBtn_" + file.index + "' data-index='" + file.index + "' onclick='funBindDelEvent("+file.index+")' src='../images/health/delete_icon.png' class='revImg file_del'/>" ; html += ' <input name="upload_image" style="display:none;" value="'+tempImgUrl+'">'; html += "</i>"; return html; }; /** * 功能:調用核心插件 參數: 無 返回: 無 */ this.createCorePlug = function() { $("#addExmInfo").attr("action", para.url); var params = { fileInput : $("#fileImage").get(0), uploadInput : $("#submitButton").get(0), url : $("#addExmInfo").attr("action"), filterFile : function(files) { // 過濾合格的文件 return self.funFilterEligibleFile(files); },
//5.(緊接着zyFile.js 的流程)獲取的圖片在這裏進行解析,獲取image對象,調用圖片壓縮方法,調用添加預覽圖片的方法
onSelect : function(selectFiles, allFiles) { para.onSelect(selectFiles, allFiles); // 回調方法 var html = '', i = 0; // 組織預覽html var funDealtPreviewHtml = function() { file = selectFiles[i]; mask_element_continuious(); if (file) {
//6.經過FileReader 這個js的原生對象,獲取圖片對象,FileReader 獲取的圖片數據是通過base64位編碼的圖片 var reader = new FileReader() reader.onload = function(e) { // 7.建立一個image對象 var img = new Image;
//8.接收reader中獲取的圖片數據,傳遞給iamge對象 img.src = reader.result; var dataUrl; img.onload = function() {
//9.調用resizeMe 的方法進行圖片壓縮,圖片壓縮採用canvase畫布,用canvas 自帶的圖片壓縮方法進行壓縮,這裏的圖片平移和旋轉將會直接影響你是否能成功的預覽到圖片 dataUrl = resizeMe(img, 1000,1000); // 10.將獲取的圖片在預覽區域進行展現 html += self.funDisposePreviewHtml(file, dataUrl); i++; // 再接着調用此方法遞歸組成能夠預覽的html funDealtPreviewHtml(); } } reader.readAsDataURL(file); } else { // 走到這裏說明文件html已經組織完畢,要把html添加到預覽區 funAppendPreviewHtml(html);
//11.圖片壓縮是須要一點時間的,這裏是關閉loading遮罩 $.mask_close_all(); } }; // 添加預覽html var funAppendPreviewHtml = function(html) { $("#wx_chooseimg").append(html); }; funDealtPreviewHtml(); // 顯示轉化後的統計信息 self.funSetStatusInfo(ZYFILE.funReturnNeedFiles()); }, onDelete : function(file, files) { // 移除效果 $("#uploadList_" + file.index).fadeOut(); //而且刪除節點 $("#uploadList_" + file.index).remove(); }, onComplete : function(response) { } }; ZYFILE = $.extend(ZYFILE, params); ZYFILE.init(); }; /*// 綁定刪除按鈕事件 this.funBindDelEvent = function(index) { if ($(".file_del").length > 0) { alert("刪除"); ZYFILE.funDeleteFile(parseInt(index), true); } };*/ /** * 功能:綁定事件 參數: 無 返回: 無 */ this.addEvent = function() { // 若是快捷添加文件按鈕存在 if ($("#uploadbtn").length > 0) { // 綁定選擇事件 $("#uploadbtn").bind("click", function(e) { ZYFILE.fileInput.click(); }); } //上傳按鈕綁定點擊事件 if ($("#submitButton").length > 0) { // 綁定選擇事件 $("#submitButton").bind("click", function(e) { ZYFILE.funUploadFiles(); }); } }; // 初始化上傳控制層插件 this.init(); }); }; })(jQuery);
(三)java 後臺接受數據存儲到數據庫和磁盤中
前臺傳遞過來的數據是form 表單進行提交的,圖片也包含在form表單中,提交的圖片是通過base64 編碼的圖片,接受數據後首先要解碼,再往磁盤中存數據
/* * 上傳圖片的action 的方法 */ public String uploadImg(){ JsonResponseResult result=null; try{ String agentType=super.getRequest().getParameter("agentType"); String[] files=super.getRequest().getParameterValues("upload_image"); //圖片用values 進行接受 HashMap<String, Object> param=new HashMap<>(); param.put("imgs", files); if(agentType!=null){ if(agentType.equals("isIos")){ //android Thread.sleep(3000); //request 接受數據的時候作一個延時,保證數據能接受完 } }
//保存圖片的service方法 boolean flag=recordExplainService.addUploadImg(param); //TODO 這個地方的異常有問題,稍後再改 if(flag==true){ result=JsonResponseResult.createSuccess("添加圖片成功"); }else{ result=JsonResponseResult.createFalied("服務器繁忙,請稍後重試!"); } }catch(AppException app){ app.printStackTrace(); logger.info("RecordExplainAction---->upReportHosInfo"); result=JsonResponseResult.createFalied("保存圖片失敗!請聯繫管理員"); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); logger.info("RecordExplainAction---->upReportHosInfo"); result=JsonResponseResult.createFalied("保存圖片失敗!請聯繫管理員"); } super.jsonResult = JSONObject.fromObject(result).toString(); return BaseAction.JSON; }
impl
/** * @throws InterruptedException * @see 插入圖片 */ @Override public boolean addUploadImg(HashMap<String, Object> params) throws InterruptedException { boolean flag = false; String[] files=(String[]) params.get("imgs"); params.remove("imgs"); Integer count=0; List<HashMap<String, Object>> imgList = new ArrayList<>(); for (int i = 0; i < files.length; i++) { String filename = "web_"+System.currentTimeMillis() + ".jpeg"; imgList.add(img); //前臺傳遞過來的圖片是通過base64 加密的,在這裏進行解密 //String tempUrl=files[i].replace("data:image/jpg;base64,", ""); byte[] buffer=AESUtilHTBX.base64Decode(files[i]); HashMap<String, Object> hashMap=new HashMap<>(); //保存圖片到文件系統中的map //將解密出來的字節數組填充到輸入流中 InputStream fis = new ByteArrayInputStream(buffer); hashMap.put("fileName", filename); hashMap.put("pathType", 6); hashMap.put("inputstr", fis); Map<String, Object> map=this.doUploadFile("1", hashMap); //公用的圖片上傳的方法,發送一個post請求 if(map.get("flag").equals("1")){ ++count; } } if(count==files.length){ //將基本數據持久化到數據庫中 flag=true; } return flag; }
base64 解碼方法
/** * base64解碼 * * @param base64Code * 待解碼的base64字符串 * @return 解碼後的字節數組 * @throws Exception */ public static byte[] base64Decode(String base64Str) { return Base64.decodeBase64(base64Str); }
往磁盤中插入圖片
/** * 上傳圖片 * @return * @throws IOException */ public String doPostFile() throws IOException { JsonResponseResult result = null; PrintWriter out = super.getResponse().getWriter(); try { String savaPath = ""; String pathType = super.getRequest().getParameter("pathType"); String fileName = super.getRequest().getParameter("fileName"); String mobile1 = super.getRequest().getParameter("mobile"); savaPath = propsLoader.props.getProperty("savePath") + mobile1 + "\\"; File tempFile = new File(savaPath); if (!tempFile.exists()) { tempFile.mkdirs(); } ServletInputStream input = super.getRequest().getInputStream(); // file文件流 File outFile = null; FileOutputStream outStream = null; byte[] buffer = new byte[1024]; int l = 0; outFile = new File(savaPath + fileName); outStream = new FileOutputStream(outFile); while ((l = input.read(buffer)) > 0) { outStream.write(buffer, 0, l); } l = 0; outStream.flush(); outStream.close(); input.close(); /*if(pathType.equals("3")){ //壓縮圖片 pictureCutService.imgCut("3", fileName); }*/ HashMap<String, String> map = new HashMap<String, String>(); map.put("flag", "1"); map.put("fileName", fileName); String jsonData = JSONObject.fromObject(map).toString(); out.print(jsonData); } catch (final AppException app) { this.logger.error(app); HashMap<String, String> map = new HashMap<String, String>(); map.put("flag", "0"); String jsonData = JSONObject.fromObject(map).toString(); out.print(jsonData); final String msg = this.getText(app.getMessage()); result = JsonResponseResult.createFalied(msg); super.jsonResult = JSONObject.fromObject(result).toString(); } catch (final Exception e) { this.logger.error(e); HashMap<String, String> map = new HashMap<String, String>(); map.put("flag", "0"); String jsonData = JSONObject.fromObject(map).toString(); out.print(jsonData); final String msg = getText("com.sgfm.datacenter.action.order.OrderAction.exception"); result = JsonResponseResult.createFalied(msg); super.jsonResult = JSONObject.fromObject(result).toString(); } return BaseAction.JSON; }
這裏的java 方法不能直接用,須要本身去結合本身的項目去寫。這裏只列出來幾點重要處理:圖片的base64 解碼、經過輸入輸出流往磁盤中寫圖片文件
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><!DOCTYPE html><html lang="en"><head><script type="text/javascript">var _speedMark = new Date();</script><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /><meta content="" name="keywords"/> <meta content="" name="description"/><title>上傳圖片頁面</title><link rel="stylesheet" type="text/css" href="/css/healthRecords.css" /><!-- 查看大圖的css --><link rel="stylesheet" href="/css/smartphoto.css" /><!-- 查看大圖的js --><script type="text/javascript" src="/js/jquery-smartphoto.min.js" ></script><script src="/js/bootstrap.min.js" type="text/javascript" charset="utf-8"></script><!-- form 表單提交 --><script type="text/javascript" src="/js/jquery.sgfmform.js"></script><!-- 引用核心層插件 --><script type="text/javascript" src="/js/zyFile.js"></script><!-- 引用控制層插件 --><script type="text/javascript" src="/js/zyUpload.js"></script><!-- 修正ios圖片旋轉 --><script type="text/javascript" src="/js/exif.js"></script><!-- 圖片正在加載中效果 --><link rel="stylesheet" type="text/css" href="/css/loading/load.css" media="all"><script type="text/javascript" src="/css/loading/load-min.js"></script></head><body><body ><!-- form 表單須要提交的數據,能夠包含基本數據,和圖片數據 --><form id="addExmInfo" method="post" enctype="application/x-www-form-urlencoded"><div class="main" style="margin-bottom: 0;padding-bottom: 0;"><ul class="write"><li class="clearfix" onclick="openCalendar();"><span>提交人姓名</span><img src="/images/main-right.png" /><input style="display:block;" value="" id="chooseDate" name="tijianTime" onfocus="this.blur()"></li></ul></div><div class="main" id="imageMain" style="border-bottom: 50px solid #f7f9fa;"><div class="uploading" style="margin-top: 0;" id="uploadbtn" ><img src="/images/Upload_pic_icon.png" /><p class="uploadingTop">上傳報告圖片(手機上傳)</p><p class="uploadingBottom">注:請確保圖片上文字清晰可見</p></div><!-- 圖片預覽區 --><div id="wx_chooseimg" class="imgView"></div></div><!-- 瀏覽器類型:微信瀏覽器或者非微信瀏覽器 --><input value="" type="hidden" id="agentType" name="agentType"/><!-- 刪除的圖片id --><input type="hidden" id="delIds" name="delIds"/><input type="button" id="submitButton" value="保存" class="btn btn-block main-btn save" /></form><!-- 真正觸發獲取手機相冊的元素 --> <input id="fileImage" style="display:none;" type="file" accept="image/*" size="30" name="imgSelected" multiple> <input id="state" type="hidden" /> <!-- 圖片加載中效果 --> <div id="test_mask_2" class="test_mask"></div></body><script type="text/javascript">$(document).ready(function () {// 初始化圖片插件$("#addExmInfo").zyUpload({width : "1000px", // 寬度height : "500px", // 寬度itemWidth : "120px", // 文件項的寬度itemHeight : "100px", // 文件項的高度url : "/core/recordExplain.upReportInfoWeb.do", // 上傳文件的路徑multiple : true, // 是否能夠多個文件上傳dragDrop : true, // 是否能夠拖動上傳文件del : true, // 是否能夠刪除文件finishDel : false, // 是否在上傳文件完成後刪除預覽/* 外部得到的回調接口 */onSelect: function(files, allFiles){ // 選擇文件的回調方法},onDelete: function(file, surplusFiles){ // 刪除一個文件的回調方法console.info(file);},onSuccess: function(file){ // 文件上傳成功的回調方法},onFailure: function(file){ // 文件上傳失敗的回調方法},onComplete: function(responseInfo){ // 上傳完成的回調方法}}); $(".img_viwer").smartPhoto({ resizeStyle: 'fit' }); /* 這是form表單提交的js ,直接用form表單提交,不用這個js也可 */$("#addExmInfo").sgfmform({ ajaxurl : "/core/recordExplain.upReportInfoWeb.do", tiptype : 1, submittype : 2, callback : function(data,url){ if(data.returncode == 0){ alert("圖片上傳成功"); }else{ alert("圖片上傳失敗"); } $("#submitButton").attr('disabled',false); $("#submitButton").css("background-color","#05A3FF"); }});});/* 圖片刪除綁定點擊事件 */function funBindDelEvent(index) { if ($(".file_del").length > 0) { confirmMsg("確認刪除圖片?",function(){ ZYFILE.funDeleteFile(parseInt(index), true); }); }};/* 圖片正在加載中 */function mask_element_continuious() {$.mask_element('#test_mask_2',3000);}</script></html>