基于SpringMVC的文件下载实例

来源:互联网 发布:商业游戏源码论坛 编辑:程序博客网 时间:2024/06/05 14:21
转自:http://983836259.blog.51cto.com/7311475/1835373/
文件的下载和文件的上传一样都是Web应用中一个重要的功能点。这篇“SpingMVC的文件下载”是基于以前写过的那篇“SpringMVC实现文件上传”写的,因此这里就不从头开始搭建测试项目了,直接接着上次的那个项目来进行测试,因此看这篇文章之前需要简单浏览下上次的那篇文章

注:SpringMVC实现文件上传:http://www.zifangsky.cn/406.html

(1)在UploadController.java这个controller里的upload方法中添加返回上传之后的文件的文件名:

1
modelAndView.addObject("picName", targetFileName);

添加之后,这个方法的完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ModelAndView upload(User user, @RequestParam("file") MultipartFile tmpFile, HttpServletRequest request) {
    ModelAndView modelAndView = new ModelAndView("fileupload");
 
    if (tmpFile != null) {
        // 获取物理路径
        String targetDirectory = request.getSession().getServletContext().getRealPath("/uploads");
        String tmpFileName = tmpFile.getOriginalFilename(); // 上传的文件名
        int dot = tmpFileName.lastIndexOf('.');
        String ext = ""// 文件后缀名
        if ((dot > -1) && (dot < (tmpFileName.length() - 1))) {
            ext = tmpFileName.substring(dot + 1);
        }
        // 其他文件格式不处理
        if ("png".equalsIgnoreCase(ext) || "jpg".equalsIgnoreCase(ext) || "gif".equalsIgnoreCase(ext)) {
            // 重命名上传的文件名
            String targetFileName = StringUtile.renameFileName(tmpFileName);
            // 保存的新文件
            File target = new File(targetDirectory, targetFileName);
 
            try {
                // 保存文件
                FileUtils.copyInputStreamToFile(tmpFile.getInputStream(), target);
            catch (IOException e) {
                e.printStackTrace();
            }
 
            User u = new User();
            u.setUserName(user.getUserName());
            u.setLogoSrc(request.getContextPath() + "/uploads/" + targetFileName);
 
            modelAndView.addObject("u", u);
            modelAndView.addObject("picName", targetFileName);
        }
 
        return modelAndView;
    }
 
    return modelAndView;
}

(2)在fileupload.jsp这个文件中添加一个文件下载的超链接:

1
2
<h2>头像下载</h2>      
    <a href="download.html?fileName=${picName}">点击下载</a>

可以看出,这里的fileName就是用的controller中的“picName”来赋值的

wKioL1em85DRgyrvAACsazjzfzg323.png

注:代码添加的位置如上图所示

(3)在UploadController.java中添加一个用于下载文件的方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RequestMapping(value = "/download", method = { RequestMethod.GET, RequestMethod.POST })
public ResponseEntity<byte[]> download(@RequestParam(name = "fileName") String fileName,
        HttpServletRequest request) {
    HttpHeaders headers = new HttpHeaders();
    Pattern pattern = Pattern.compile("\\w*\\.\\w+");
    Matcher matcher = pattern.matcher(fileName);
     
    //检查文件名中非法字符,只允许是字母、数字和下划线
    if (matcher.matches()) {
        try {
            headers.setContentDispositionFormData("myfile", fileName);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            // 获取物理路径
            String filePath = request.getSession().getServletContext().getRealPath("/uploads");
            File pic = new File(filePath, fileName);
            return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(pic), headers, HttpStatus.CREATED);
        catch (Exception e) {
            e.printStackTrace();
        }
    }
     
    return null;
}

注:从上面的代码可以看出,通过接收表示文件名的字符串然后跟文件的路径拼接起来,形成文件在磁盘中真实路径的File对象,最后返回文件的流并进行下载。需要注意的是,为了防止出现任意文件下载,导致下载到其他路径中的文件,因此在下载之前校验了文件名的格式。同时最后返回了一个ResponseEntity<byte[]>类型的数据,是为了在返回数据流的同时返回我们自定义的HttpHeaders和HttpStatus

(4)最后下载的效果如下:

wKiom1em873C4HbmAAFpQB9gwPM589.jpg