springmvc图片上传、jquery 图片上传预览

宽为限 紧用功 功夫到 滞塞通

简介

项目需求,需要做图片上传功能,图片上传肯定得给个预览嘛,然后就找了下面这个方案

ajaxfileupload插件上传

ajaxfileupload.js网上传了好几个版本,选择自己可以使用的就好了。这个插件是N多年前写的了,估计后期作者没有继续维护,所以才出来多个版本吧,第一版的话现在最新jquery中使用的话会报错 handleError not find

ajaxfileupload现在来讲比较古老了,它以来jquery,而且是1.4.2版本的,那时候1.4.2版本的jQuery有handlerError方法,到了现在的1.9+就没有了,所以会报handlerError找不到的错误,解决方法是:找到ajaxfileupload.js文件,在 ” jQuery.extend({ “之后加上一下代码,就可以了!

所以在该文件中添加上 handleError函数

handleError: function (s, xhr, status, e) {
        if (s.error) {
            s.error.call(s.context || s, xhr, status, e);
        }
        if (s.global) {
            (s.context ? jQuery(s.context) : jQuery.event).trigger("ajaxError", [xhr, s, e]);
        }
    },

前端页面代码

jsp代码
<tr>
<td style="text-align:right;">产品详情图:</td>
<td>
 <input type="file"  multiple="multiple" accept="image/gif,image/jpeg,image/png,image/jpg,image/bmp" id="chanpinzhutu" name="chanpinzhutu" onchange="setImagePreviews()" class="hide"/>
 <label for="chanpinzhutu" class="labelBtn2">本地上传(最多选择6张)</label>
</td>
</tr>
<tr>
<td style="text-align:right;"></td>
<td>
 <c:if test="${empty model.productPhotos['0'] }">
 <img id="chanpinzhutu0" src="127.0.0.1:8080/test/images/empty_mid.png" width="80" height="80"/>
 <img id="chanpinzhutu1" src="127.0.0.1:8080/test/images/empty_mid.png" width="80" height="80"/>
 <img id="chanpinzhutu2" src="127.0.0.1:8080/test/images/empty_mid.png" width="80" height="80"/>
 <img id="chanpinzhutu3" src="127.0.0.1:8080/test/images/empty_mid.png" width="80" height="80"/>
 <img id="chanpinzhutu4" src="127.0.0.1:8080/test/images/empty_mid.png" width="80" height="80"/>
 <img id="chanpinzhutu5" src="127.0.0.1:8080/test/images/empty_mid.png" width="80" height="80"/>
 </c:if>
 <c:if test="${not empty model.productPhotos['0'] }">
    <c:forEach varStatus="i" var="img0" items="${model.productPhotos['0'] }">
    <img id="chanpinzhutu${i.index }" src="${img0.imageLink }"  width="80" height="80"/>
    </c:forEach>
 </c:if>
</td>
</tr>
js代码
// 展示详情图
function ajaxFileUploadMax() {
    $.ajaxFileUpload ({
        url: '127.0.0.1:8080/test/imgUploadMax?model=${model.fdId}', //用于文件上传的服务器端请求地址
        secureuri: false, //是否需要安全协议,一般设置为false
        fileElementId: 'chanpinzhutu', //文件上传域的ID
        dataType: 'json', //返回值类型 一般设置为json
        //服务器成功响应处理函数
        success: function (data, status) {
            //转换后的JSON对象
            var obj = new Function("return" + data)();
            var i = 0;
            for(i; i < obj.length; i++){  
                //显示预览
                 $("#chanpinzhutu"+i).attr("src", obj[i]);
            }

        },
        //服务器响应失败处理函数
        error: function (data, status, e){
            alert(e);
            console.log(e);
        }
    })
    return false;
}

springmvc后台代码

/**
    * 多图片上传
    * @param files
    * @param request
    * @return
    * @throws Exception
    */
    @RequestMapping(value="/imgUploadMax", method=RequestMethod.POST)  
    @ResponseBody  
    public String imgUploadMax(@RequestParam(value = "chanpinzhutu", required = false) MultipartFile[] files,
        HttpServletRequest request) throws Exception {  

    String modelId = request.getParameter("model");

    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");  
    String dateNowStr = sdf.format(new Date()); 

    String path = "/soluser/official/upload/product/" + dateNowStr;

    JSONArray jsonArray = new JSONArray();
    // 最多存6张
    int fileSize = files.length > 6 ? 6 : files.length;
    for (int i = 0; i < fileSize; i++) {

        MultipartFile file = files[i];
        String originalFilename =  file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileNameStr = (new Date().getTime()) + substring;  
        File targetFile = new File(path, fileNameStr);  
        if(!targetFile.exists()){  
            targetFile.mkdirs();  
        }  
        //保存  
        try {  
            file.transferTo(targetFile);
            String imageLink = path + "/" + fileNameStr;
            jsonArray.add(imageLink);

        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }

        return jsonArray.toString();  
    }  

后台代码就是简单springmvc文件上传,MultipartFile 获取上传文件,保存并返回存储地址。
前端js获取后台传过来的保存地址,放到img标签上,然后展示上传的图片。
这里获取返回数据是遇到了问题,就是返回的data 在ajaxfileupload插件处理时报错了
我们看看它是如何处理返回数据的

uploadHttpData: function( r, type ) {
        var data = !type;
        data = type == "xml" || data ? r.responseXML : r.responseText;
        // If the type is "script", eval it in global context
        if ( type == "script" )
            jQuery.globalEval( data );
        // Get the JavaScript object, if JSON is used.
        if ( type == "json" )
        {
            // If you add mimetype in your response,
            // you have to delete the '<pre></pre>' tag.
            // The pre tag in Chrome has attribute, so have to use regex to remove
            /*var data = r.responseText;
            var rx = new RegExp("<pre.*?>(.*?)</pre>","i");
            var am = rx.exec(data);
            //this is the desired data extracted
            var data = (am) ? am[1] : "";    //the only submatch or empty
            eval( "data = " + data );*/
            // data=eval('(' + data+ ')');        // evaluate scripts within html  
            return data;

        }
        // evaluate scripts within html
        if ( type == "html" )
            jQuery("<div>").html(data).evalScripts();
        //alert($('param', data).each(function(){alert($(this).attr('value'));}));
        return data;
    },

if ( type == "json" )这里我把它所有的处理都去掉了,因为我知道后台传递的数据所以这里就不需要特殊处理了。

略讲一下ajaxfileupload上传的原理,看createUploadIframecreateUploadForm,大概你就能猜到它的原理了。没错,它就是在页面上给你嵌套一个隐藏页面,页面里有个用于上传提交的Form,js代码将原来Form里的文件域里的信息放到隐藏页面里的Form中来,所以图片上传就被抽离出来了。

图片时展示了,但这是上传后再展示的,觉得有点别扭,要是后面还要修改的话岂不是服务器里要存一堆的图片!能不能先预览,等form表单提交时图片才保存呢? 于是有了第二种方案:

方案2

主表单没提交前就不保存图片,那么如果是ajax提交上来的图片后台就不给它保存,那前端这么显示预览呢?,对了,返回base64编码,浏览器可以解析base64编码的图片。然后后台就讲传过来的文件编码后再返回过去,嗯!感觉挺OK的,嘚瑟中…
后面想想这样是不是太傻逼了, 为什么不直接再前端就转码呢!(⊙o⊙)…
由于技术不足,然后又是各种找js base64编码方式,最后竟然没有一个成功的,,,解码的就随试随灵。(⊙﹏⊙)b,这个想法暂时放弃,然后突然记起以前学校时实现过图片即时浏览的功能,最后找到了它了 URL.createObjectURL就这个东东,具体的看这里URL.createObjectURL和URL.revokeObjectURL

第二版代码

jsp代码
<tr>
    <td style="text-align:right;">主页展示图:</td>
    <td>
     <input type="file" accept="image/gif,image/jpeg,image/png,image/jpg,image/bmp" 
        id="suoluetu" name="suoluetu"  onchange="setImagePreviews1('suoluetu', 'showLittle')" class="hide"/>
     <label for="suoluetu" class="labelBtnAdd">+</label>
     <%-- 旧图片 --%>
     <div id="oldImg1">
     <c:if test="${not empty model.productPhotos['1'] }">
        <c:forEach varStatus="i" var="img1" items="${model.productPhotos['1'] }">
        <img id="suoluetu${i.index }" src="${img1.imageLink }"  width="60" height="60" style="margin-left: 3px;"/>
        </c:forEach>
     </c:if>
      </div>
     <%-- 临时显示 --%>
     <div id="showLittle"></div>

    </td>
   </tr>
js代码
/**
 * 图片上传预览
 * @param files
 * @param show
 * @returns
 */
function setImagePreviews1(files1, show1) {
    // 编辑时隐藏之前的图片
    $("#oldImg1").hide();

    var docObj = document.getElementById(files1);
    var dd = document.getElementById(show1);

    dd.innerHTML = "";

    var fileList = docObj.files;
    var size = fileList.length > 6 ? 6 : fileList.length;
    for (var i = 0; i < size; i++) {

        dd.innerHTML += "<div style='float:left; margin-left:5px;' > <img id='imgOne" + i
                + "'  /> </div>";
        var imgObjPreview = document.getElementById("imgOne" + i);

        if (docObj.files && docObj.files[i]) {

            // 火狐下,直接设img属性
            imgObjPreview.style.display = 'block';
            imgObjPreview.style.width = '60px';
            imgObjPreview.style.height = '60px';
            // imgObjPreview.src = docObj.files[0].getAsDataURL();
            // 火狐7以上版本不能用上面的getAsDataURL()方式获取,需要一下方式
            imgObjPreview.src = window.URL.createObjectURL(docObj.files[i]);

        } else {

            // IE下,使用滤镜
            docObj.select();
            var imgSrc = document.selection.createRange().text;
            var localImagId = document.getElementById("imgOne" + i);

            // 必须设置初始大小
            localImagId.style.width = "60px";
            localImagId.style.height = "60px";

            // 图片异常的捕捉,防止用户修改后缀来伪造图片
            try {
                localImagId.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)";
                localImagId.filters
                        .item("DXImageTransform.Microsoft.AlphaImageLoader").src = imgSrc;

            } catch (e) {
                alert("您上传的图片格式不正确,请重新选择!");
                return false;

            }

            imgObjPreview.style.display = 'none';
            document.selection.empty();

        }

    }
    return true;
}

图片选择时onchange="setImagePreviews1('suoluetu', 'showLittle')"触发函数,这里还有个梗 input file里的JQ change() 事件的只生效一次 问题
这样图片浏览就是即时的了,提交时后台获取处理就OK了,这样服务器里就存一次正确的图片了,提交之前的图片统统还在前端,随浏览器的关闭而消失。就不用担心重复上传和无效文件上传问题了。O(∩_∩)O哈哈~

站在巨人的肩膀上

本篇博文参考的文章
http://www.cnblogs.com/kissdodog/archive/2012/12/15/2819025.html
http://docs.spring.io/spring/docs/4.0.x/javadoc-api/org/springframework/web/multipart/MultipartFile.html
http://www.cnblogs.com/ChenRunCheng/p/3592359.html
http://blog.csdn.net/imlinjunjie/article/details/49403199
http://www.mamicode.com/info-detail-456059.html
http://www.h3399.cn/201705/85905.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值