1. 程式人生 > >spring實現文件上傳(圖片解析)

spring實現文件上傳(圖片解析)

handle exc 所有 sub str [] sys script ota

合抱之木,生於毫末,千裏之行,始於足下,要想了解spring的文件上傳功能,首先要知道spring是通過流的方式將文件進行解析,然後上傳。那麽是不是所有需要用的文件上傳的地方都要寫一遍文件解析器呢?

放心,spring這個大管家已經為我們做好了一切!

我們只需要在spring的配置文件中加入下面代碼:

 <!-- 文件上傳解析器 -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
        p:maxUploadSize
="152400" p:defaultEncoding="utf-8"> <!-- <property name="defaultEncoding" value="utf-8"></property> --> </bean> <!-- SpringMVC在超出上傳文件限制時,會拋出org.springframework.web.multipart.MaxUploadSizeExceededException --> <!-- 該異常是SpringMVC在檢查上傳的文件信息時拋出來的,而且此時還沒有進入到Controller方法中
--> <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- 遇到MaxUploadSizeExceededException異常時,自動跳轉到/WEB-INF/jsp/error_fileupload.jsp頁面
--> <prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">error_fileupload</prop> </props> </property> </bean>

我們就不用再去在文件的解析上絞盡腦汁了,只需要專註於業務層面的邏輯就好了,是不是很簡單?

接下來我們看一個小例子:

html前端代碼:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<form action="<%=request.getContextPath()%>/user/add" method="post" enctype="multipart/form-data">
    
    
    <h1>新增用戶</h1>
    
    <table>
        <tr>
            <td>用戶名:</td>
            <td>
                <input type="text" name="userName" value="${user.userName }" />
            </td>
        </tr>
        <tr>
            <td>密碼:</td>
            <td>
                <input type="text" name="password" value="${user.userPass }" />
            </td>
        </tr>
        <tr>
            <td>頭像:</td>
            <td>
                <input type="file" name="photo" />
            </td>
        </tr>
        <tr>
            <td></td>
            <td>
                <input type="submit" value="上傳" />
            </td>
        </tr>
    </table>
</form>

</body>
</html>

大家有沒有註意到以上代碼的form表頭中有一行代碼:

enctype="multipart/form-data"

沒錯,想要上傳二進制文件,該表頭屬性必不可少。
controller控制層代碼:
package com.wskj.springmvc.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.wskj.springmvc.pojo.UserInfo;

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping(value="/add", method=RequestMethod.GET)
    public String addUser(){
        
        return "user/add";
    }
    
    @RequestMapping(value="/add", method=RequestMethod.POST)
    public String addUser(Model model, UserInfo user, @RequestParam(name="photo", required=false) MultipartFile photo, HttpServletRequest request) throws IOException{
        
        //對文件進行處理
        
        //判斷用戶是否上傳了文件
        //MultipartFile.getSize() : 獲取文件的大小(字節:byte)  1024byte = 1kb   1024kb=1mb   GB  TB  PB
        if(photo.isEmpty() == false && photo.getSize() > 0){
            
            //獲取文件的名稱
            String name = photo.getName();//photo
            String fileName = photo.getOriginalFilename();//mydata.jpg
            //獲取文件擴展名
            String extension = fileName.substring(fileName.lastIndexOf("."));
            
            byte[] data = photo.getBytes();//字節數組
            String contentType = photo.getContentType();
            /**
             * 擴展名      Content-Type
             * .txt     text/plain
             * .jpg  image/jpeg
             * .mp3     audio/mp3
             * .mp4     video/mpeg4
             */
            
            photo.getInputStream();//獲取文件輸入流
            
            //保存到磁盤
            //保存的路徑
            //不是 -》 F:\java\workspace\spring\springmvc_fileupload_20170401\WebContent\files
            //是 -》 x:\apache tomcat-7\webapps\appName\files
            String savedPath = request.getServletContext().getRealPath("files");//獲取files目錄的絕對路徑
            String filePath = savedPath + "/" + fileName;
            
            //將文件寫入磁盤
            photo.transferTo(new File(filePath));
            
            //設置UserInfo.headerPhoto
            user.setHeaderPhotoUrl("files/"+fileName);
            model.addAttribute("headerUrl", user.getHeaderPhotoUrl());
        }
        
        model.addAttribute("user", user);
        
        return "user/success";
    }
    
    @RequestMapping(value="/add2", method=RequestMethod.GET)
    public String addUser2(){
        
        return "user/add2";
    }
    
    @RequestMapping(value="/add2", method=RequestMethod.POST)
    public String addUser2(Model model, UserInfo user, @RequestParam(name="photos", required=false) MultipartFile[] photos, HttpServletRequest request) throws IOException{
        
        //對文件進行處理
        
        if(photos != null && photos.length>0){
            List<String> photoUrls = new ArrayList<String>();
            for(MultipartFile photo : photos){
                
                //判斷用戶是否上傳了文件
                //MultipartFile.getSize() : 獲取文件的大小(字節:byte)  1024byte = 1kb   1024kb=1mb   GB  TB  PB
                if(photo.isEmpty() == false && photo.getSize() > 0){
                    
                    //獲取文件的名稱
                    String name = photo.getName();//photo
                    String fileName = photo.getOriginalFilename();//mydata.jpg
                    //獲取文件擴展名
                    String extension = fileName.substring(fileName.lastIndexOf("."));
                    
                    byte[] data = photo.getBytes();//字節數組
                    String contentType = photo.getContentType();
                    /**
                     * 擴展名      Content-Type
                     * .txt     text/plain
                     * .jpg  image/jpeg
                     * .mp3     audio/mp3
                     * .mp4     video/mpeg4
                     */
                    
                    photo.getInputStream();//獲取文件輸入流
                    
                    //保存到磁盤
                    //保存的路徑
                    //不是 -》 F:\java\workspace\spring\springmvc_fileupload_20170401\WebContent\files
                    //是 -》 x:\apache tomcat-7\webapps\appName\files
                    String savedPath = request.getServletContext().getRealPath("files");//獲取files目錄的絕對路徑
                    String filePath = savedPath + "/" + fileName;
                    
                    //將文件寫入磁盤
                    photo.transferTo(new File(filePath));
                    
                    //設置UserInfo.headerPhoto
                    
                    photoUrls.add("files/"+fileName);
                }
                
            }
            
            model.addAttribute("headerUrl", photoUrls);
        
        }
        
        model.addAttribute("user", user);
        
        return "user/success2";
    }
    
}

後臺根據前段的name屬性接收參數,二進制文件類型為

MultipartFile,如果需要接收多個文件,只需要設置成集合然後遍歷即可。
接下來是上傳成功前段回顯的jsp代碼:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

    <dl>
        <dt>用戶名:</dt>
        <dd>${user.userName }</dd>
        <dt>頭像:</dt>
        <dd>
            <img style="max-width:300px;max-height:200px;" src="<%=request.getContextPath() %>/${headerUrl}" />
        </dd>
    </dl>

</body>
</html>

至此,最基礎的文件上傳測試成功。

技術分享

技術分享

但是,在實際項目中,我們可能只是需要啟用一個div來進行文件的異步上傳,這時我們可以使用html5的新特性formdata實現ajax的提交。

具體代碼如下:

jsp前端代碼:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="<%= request.getContextPath()%>/static/jquery-1.10.2.js"></script>
<script type="text/javascript">

$(function(){

    $("#btnupload").click(function(){
        
        var formdata = new FormData(document.getElementById("form1"));//可以上傳文件
        //var formdata = $("#form1").serializeArray();//無法上傳文件的
        alert(formdata);
        var url ="<%= request.getContextPath()%>/upload/demo1";
        $.ajax({
            url:url,
            data:formdata, //name=zhangsan&age=50   {}
            contentType: false,//默認: "application/x-www-form-urlencoded"
            processData: false,//設置 processData 選項為 false,防止自動轉換數據格式
            type:"post",
            dataType:"json",
            success:function(data){
                alert(data);
            },
            error:function(er){
                alert(er.responseText);
            }
        });
        
        
    });
});

</script>

</head>
<body>

    <h1>使用Html5提供的FormData實現ajax提交</h1>
    <h3>瀏覽器必須支持html5,如果是IE6 - IE8,那就洗洗睡吧...</h3>

    <form id="form1">
        文件名:<input type="text" name="fileName" />
        文件:<input type="file" name="myfile" />
        <input id="btnupload" type="button" value="ajax上傳文件" />
    </form>


</body>
</html>

我們可以看見,只需要給要提交的form表單指定一個唯一標識id即可,是不是很方便?

後臺controller接收代碼:

package com.wskj.uploadfile.controller;

import java.io.File;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping("/upload")
public class AjaxController {

    @RequestMapping(value="/demo1", method=RequestMethod.GET)
    public String demo1(){
        return "upload/demo1";
    }
    
    @RequestMapping(value="/demo1", method=RequestMethod.POST)
    @ResponseBody
    public boolean demo1(String fileName, MultipartFile myfile, HttpServletRequest request) throws IllegalStateException, IOException{
        
        String path = request.getServletContext().getRealPath("files");
        path += "/" + myfile.getOriginalFilename();
        File file = new File(path);
        myfile.transferTo(file);
        
        System.out.println(fileName+" - 上傳成功");
        
        return true;
    }
    
}

另外還可以使用jquery.form.js實現ajax的上傳:

前段jsp代碼:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="<%= request.getContextPath()%>/static/jquery-1.10.2.js"></script>
<script type="text/javascript" src="<%= request.getContextPath()%>/static/jquery.form.js"></script>
<script type="text/javascript">

$(function(){

    $("#btnupload").click(function(){

        var url ="<%= request.getContextPath()%>/upload/demo2";
        
        $("#form1").ajaxSubmit({  
            type:post,  
            url:url,  
            clearForm:true,//清空所有表單元素的值
            resetForm:true,//重置所有表單元素的值
            success:function(data){  
                alert(data);  
            },  
            error:function(XmlHttpRequest,textStatus,errorThrown){  
                alert("上傳失敗了");
            }  
        });  
        
    });
});

</script>

</head>
<body>

    <h1>使用jquery.form.js實現ajax文件上傳</h1>
    <h3>對瀏覽器沒有限制,盡情使用吧騷年們...</h3>

    <form id="form1">
        文件名:<input type="text" name="fileName" value="我的頭像" />
        文件:<input type="file" name="myfile" />
        <input id="btnupload" type="button" value="ajax上傳文件" />
    </form>


</body>
</html>

後臺controller接收代碼:

package com.wskj.uploadfile.controller;

import java.io.File;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping("/upload")
public class AjaxController {

   
    
    
    
    @RequestMapping(value="/demo2", method=RequestMethod.GET)
    public String demo2(){
        return "upload/demo2";
    }
    
    @RequestMapping(value="/demo2", method=RequestMethod.POST)
    @ResponseBody
    public boolean demo2(String fileName, MultipartFile myfile, HttpServletRequest request) throws IllegalStateException, IOException{
        
        String path = request.getServletContext().getRealPath("files");
        path += "/" + myfile.getOriginalFilename();
        File file = new File(path);
        myfile.transferTo(file);
        
        System.out.println(fileName+" - 上傳成功");
        
        return true;
    }
    
    
}

當然,使用這兩種方法也必須在spring中配置文件上傳解析器,這個是上傳二進制文件的前提。

spring實現文件上傳(圖片解析)