移动端 H5 拍照 从手机选择图片,移动端预览,图片压缩,图片预览,再上传服务器

前言:最近公司的项目在作全网营销,要作非微信浏览器的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>

相关文章
相关标签/搜索