(笔记)Spring MVC学习指南_上传文件

在Spring MVC中处理文件上传有两种方法:
(1)Apache Commons FileUpload元件
(2)利用Servlet 3.0及其更高版本的内置支持。如果要将应用程序部署到支持Servlet 3.0及其更高版本的容器中,只能使用这种方法。
无论选择哪一种方法,都要利用相同的API来处理已经上传的文件。
1.客户端编程
为了上传文件,必须将HTML表格的enctype属性值设为multipart/form-data,像下面这样:

"action" enctype="multipart/form-data" method="post"> Select a file type="file" name="fieldName" /> type="submit" value="Upload" />

表格中必须包含类型为file的一个input元素,它会显示成一个按钮,点击时,它会打开一个对话框,用来选择文件。
在HTML5之前,如果想要上传多个文件,必须使用多个文件input元素。但是,在HTML5中,通过在input元素中引入多个multiple属性,使得多个文件的上传变得更加简单。在HTML5中编写以下任意一行代码,便可生成一个按钮供选择多个文件:

type="file" name="fieldName" multiple/>
type="file" name="fieldName" multiple="multiple"/>
type="file" name="fieldName" multiple=""/>

2.MultipartFile接口
在Spring MVC中处理已经上传的文件十分容易。上传到Spring MVC应用程序中的文件会被包在一个MultipartFile对象中。你唯一的任务就是用类型为MultipartFile的属性编写一个domain类。
org.springframework.web.multipart.MultipartFile接口具有以下方法:
byte[] getBytes()
它以字节数组的形式返回文件的内容。
String getContentType()
它返回文件的内容类型。
InputStream getInputStream()
它返回一个InputStream,从中读取文件的内容。
String getName()
它以多部分的形式返回参数的名称。
String getOriginalFilename()
它返回客户端本地驱动器中的初始文件名。
long getSize()
它以字节为单位,返回文件的大小。
boolean isEmpty()
它表示被上传的文件是否为空。
void transferTo(File destination)
它将上传的文件保存到目标目录下。
3.用Commons FileUpload上传文件
需要在Spring MVC配置文件中定义multipartResolver bean。

    id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="2000000" />
    

4.Domain类
这个类具有类型为List的images属性。

package app11a.domain;


import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.validation.constraints.Past;
import javax.validation.constraints.Size;

import org.springframework.web.multipart.MultipartFile;

import com.sun.istack.internal.NotNull;


public class Product implements Serializable
{

    private static final long serialVersionUID = -164834188493691288L;

    @NotNull
    @Size(min = 1, max = 10)
    private String name;

    @NotNull
    private String description;

    private Float price;

    @Past
    private Date productionDate;

    private List images;
    ...

5.控制器
保存已上传文件是一件很轻松的事情,只需要在MultipartFile中调用transferTo方法。

package app11a.controller;


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

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import app11a.domain.Product;


@Controller
public class ProductController
{

    private static final Log logger = LogFactory.getLog(ProductController.class);

    @RequestMapping(value = "/product_input")
    public String inputProduct(Model model)
    {
        model.addAttribute("product", new Product());
        return "ProductForm";
    }

    @RequestMapping(value = "/product_save")
    public String saveProduct(HttpServletRequest servletRequest,
                              @Valid @ModelAttribute Product product, BindingResult bindingResult,
                              Model model)
    {
        if (bindingResult.hasErrors())
        {
            FieldError fieldError = bindingResult.getFieldError();
            logger.info("Code:" + fieldError.getCode() + ",field:" + fieldError.getField());
            return "ProductForm";
        }
        List files = product.getImages();
        List fileNames = new ArrayList();
        if (null != files && files.size() > 0)
        {
            for (MultipartFile multipartFile : files)
            {
                String fileName = multipartFile.getOriginalFilename();
                fileNames.add(fileName);
                File imageFile = new File(getPath(servletRequest), fileName);
                try
                {
                    multipartFile.transferTo(imageFile);
                }
                catch (IllegalStateException e)
                {
                    e.printStackTrace();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        // save product here
        model.addAttribute("product", product);
        return "ProductDetails";
    }

    private String getPath(HttpServletRequest servletRequest)
    {
        String pathUrl = servletRequest.getServletContext().getRealPath("/image");
        File path = new File(pathUrl);
        if (!path.exists() || !path.isDirectory())
        {
            path.mkdir();
        }
        return pathUrl;
    }

}

6.配置文件
利用multipartResolver bean的maxUploadSize属性,可以设置能够接受的最大文件容量。如果没有设置这个属性,则没有最大文件容量限制。文件容量没有设置限制,并不意味着可以上传任意大小的文件。上传过大的文件时要花很长的时间,这样会导致服务器超时。为了处理超大文件的问题,可以利用HTML 5 File API将文件切片,然后再分别上传这些文件。
9.用Servlet 3及其更高版本上传文件
有了Servlet 3,就不需要Commons FileUpload和Commons IO元件了。在Servlet 3及其以上版本的容器中进行服务器端文件上传的编程,是围绕着标注类型MultipartConfig和javax.servlet.http.Part接口进行的。处理已上传文件的Servlets必须以@MultipartConfig进行标注。
下列是可能在MultipartConfig标注类型中出现的属性,它们都是可选的:
maxFileSize:上传文件的最大容量,默认值为-1,表示没有限制。大于指定值的文件将会遭到拒绝。
maxRequestSize:表示多部分HTTP请求允许的最大容量,默认值为-1,表示没有限制。
location:表示在Part调用write方法时,要将已上传的文件保存到磁盘中的位置。
fileSizeThreshold:上传文件超出这个容量界限时,会被写入磁盘。
Spring MVC的DispatcherServlet处理大部分或者所有请求。令人遗憾的是,如果不修改源代码,将无法对Servlet进行标注。但值得庆幸的是,Servlet 3中有一种比较容易的方法,能使一个Servlet变成一个MultipartConfig Servlet,即给部署描述符(web.xml)中的Servlet声明赋值。以下代码与用@MultipartConfig给DispatcherServlet进行标注的效果一样。

    <servlet>
        <servlet-name>springmvc</servlet-name>
            <servlet-class>
                org.springframework.web.servlet.DispatcherServlet
            </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/config/springmvc-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <multipart-config>
            <max-file-size>20848820</max-file-size>
            <max-request-size>418018841</max-request-size>
            <file-size-threshold>1048576</file-size-threshold>
        </multipart-config>
    </servlet>

此外,还需要在Spring MVC配件文件中使用一个不同的多部分解析器,像下面这样:

    id="multipartResolver"
    class="org.springframework.web.multipart.support.StandardServletMultipartResolver" />

你可能感兴趣的:(SpringMVC)