Spring MVC的文件上传和下载以及拦截器

Spring MVC会根据请求方法的签名不同,将请求消息中的信息以一定的方式转换并绑定到请求方法的参数中。

1.文件上传

文件上传,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有这样,才能将文件的二进制数据发送给服务器。

Spring 3.0规范提供了方法来处理文件上传,但是这种上传需要在Servlet中完成。而Spring MVC封装了上传功能,使用了Apache Commons FileUpload技术来实现了一个MultipartResolver实现类。

  • Spring MVC依赖的组件包
compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.3'
  • xml配置
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize">
        <value>10485760</value>
    </property>
    <property name="defaultEncoding">
        <value>UTF-8</value>
    </property>
</bean>
  • 后台代码

新建上传FileModel

public class FileDataModel implements Serializable {
    private String filename;

    private MultipartFile file;

    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public MultipartFile getFile() {
        return file;
    }

    public void setFile(MultipartFile file) {
        this.file = file;
    }
}

Controller代码
@Controller
@RequestMapping("file")
public class FileController {

    @RequestMapping("upload")
    public String upload() {
        return "upload";
    }

    @RequestMapping(value = "upload", method = RequestMethod.POST)
    public String uoload(FileDataModel fileDataModel, HttpServletRequest request, Model model) {
        FileResult fileResult = new FileResult();
        try {
            if (fileDataModel.getFilename().isEmpty() || fileDataModel.getFile() == null)
                throw new IllegalArgumentException("上传文件名称为空或者无上传文件");
            String filePath = request.getServletContext().getRealPath("/files");
            String filename = fileDataModel.getFile().getOriginalFilename();
            File savePath = new File(filePath, filename);
            if (!savePath.getParentFile().exists())
                savePath.getParentFile().mkdir();
            fileDataModel.getFile().transferTo(new java.io.File(filePath + java.io.File.separator + filename));
            fileResult.setTitle("上传成功");
            fileResult.setMessage("上传成功");
            fileResult.setSuccess(true);
        } catch (Exception ex) {
            fileResult.setTitle("上传失败!");
            fileResult.setMessage(ex.getMessage());
        }
        model.addAttribute("fileResult", fileResult);
        return "fileresult";
    }
}

前台JSP页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Upload</title>
</head>
<body>
<form action="/file/upload" enctype="multipart/form-data" method="post">
    <table>
        <tr>
            <td>文件描述:</td>
            <td><input type="text" name="filename"/></td>
        </tr>
        <tr>
            <td>请选择文件:</td>
            <td><input type="file" name="file"/></td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="上传"/>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

1.1Spring MVC的MultipartFile的常用方法

获取文件数据

  • 1.[] getBytes() throws IOException;

获取文件的MIME类型,如image/jpeg等

  • 2.String getContentType();

获取文件流

  • 3.InputStream getInputStream() throws IOException;

获取表单中文件组件的名字

  • 4.String getName();

获取上传文件的原名

  • 5.String getOriginalFilename();

获取文件的字节大小,单位为byte

  • 6.long getSize();

是否有上传的文件

  • 7.boolean isEmpty();

将上传文件保存到一个目标文件中

  • 8.void transferTo(File dest) throws IOException, IllegalStateException;

2.文件下载

Spring MVC提供了一个ResponseEntity类型,使用它可以很方便的定义返回的HttpHeader和HttpStatus

@RequestMapping("download")
public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename, Model model) {
ResponseEntity<byte[]> responseEntity = null;
try {
    String path = request.getServletContext().getRealPath("/files");
    String realPath = path + File.separator + filename;
    File file = new File(realPath);
    HttpHeaders headers = new HttpHeaders();
    String downFileName = new String(filename.getBytes("UTF-8"), "iso-8859-1");
    //通知浏览器以attachment(下载方式)打开图片
    headers.setContentDispositionFormData("attachment", downFileName);
    //以二进制流数据方式进行下载
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    responseEntity = new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);

} catch (Exception ex) {
    ex.printStackTrace();
}
return responseEntity;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>${requestScope.fileResult.title}</title>
</head>
<body>
   <h1>${requestScope.fileResult.message}</h1><br/>
   <a href="/file/download?filename=${requestScope.fileResult.fileName}">${requestScope.fileResult.fileName}</a>
</body>
</html>

3.拦截器

Interceptor拦截器是Spring MVC中相当重要的功能,它的功能作用是拦截用户的请求并进行相对应的处理。比如通过拦截器进行用户权限验证,或者判断用户是否已经登录等。

Spring MVC 拦截器是可插拔式的设计。如果需要使用某个拦截器,只需要在配置文件中应用拦截器即可。

3.1 HandlerInterceptor接口

Spring MVC中的Interceptor拦截器请求是通过实现HandlerInterceptor接口来完成的。

3.2实现拦截器

  • 1.自定义类实现Spring的HandlerInterceptor接口

重要接口

该请求方法将在请求处理之前被调用。这个方法的作用是对进行调用方法前进行一些前置初始化操作,进行判断用户请求是否可以进行下去。当方法返回false的时候,后续的Interceptor及Controller都不会继续执行。

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

该方法是在perHandle返回true时,在调用目标方法处理之后,在返回视图之前调用。这时候我们可以针对Controller处理之后的ModelAndView对象进行操作。

void postHandle(
        HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
        throws Exception;

该方法是在整个请求处理结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行。主要用于清理资源。

void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;
  • 2.自定义类继承HandlerInterceptorAdapter

代码演示

  • 实现HandlerInterceptor
public class AuthorizationInterceptor implements HandlerInterceptor {

    /**
     * 不拦截用户登录页面及注册页面
     */
    private static final String[] IGNORE_URI = {"user/login", "user/signup"};

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        boolean flag = false;
        String servletPath = request.getServletPath();
        for (String url : IGNORE_URI) {
            if (servletPath.contains(url)) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            User user = (User) request.getSession().getAttribute("user");
            if (user == null) {
                request.setAttribute("message", "请先登录再访问网站");
                request.getRequestDispatcher("user/login").forward(request, response);
            } else
                flag = true;
        }
        return flag;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
  • xml配置
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/home/index"/>
        <bean class="utils.AuthorizationInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

当访问home/index的时候需要进行验证

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容