Spring MVC 实现文件的上传下载

本文详细介绍了如何使用SpringMVC实现文件的上传和下载功能。在文件上传部分,讲解了单文件和多文件上传的实现,包括JSP页面的配置、Controller处理以及配置文件的设置。在文件下载部分,展示了如何创建下载链接并实现文件的下载。同时,提到了图片加载问题和Tomcat配置的注意事项。

一、Spring MVC 实现文件的上传下载

1、文件上传

1.1 单文件上传

(1)底层使用的是 Apache fileupload 组件完成上传功能,Spring MVC 只是对其进行了封装,简化开发
pom.xml

<dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.6</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
</dependency>

(2)JSP 页面

  • input 的 type 为 file
  • form 表单的 method 设置为 post
  • form 表单的 enctype 设置为 multipart/form-data
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/file/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="img">
        <input type="submit" value="提交">
    </form>
    <img src="${src}"/>
</body>
</html>

(3)Controller

@Controller
@RequestMapping("/file")
public class UploadController {

    @PostMapping("/upload")
    public String upload(@RequestParam("img") MultipartFile img, HttpServletRequest request){
        if(img.getSize() > 0){
            String path = request.getSession().getServletContext().getRealPath("file");
            String fileName = img.getOriginalFilename();
            File filePath = new File(path);
            if(!filePath.exists()){
                filePath.mkdir();
            }
            File file = new File(path, fileName);
            try {
                img.transferTo(file);
                request.setAttribute("src", "/file/"+fileName);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "upload";
        }
        return null;
    }
}

(4)springmvc.xml

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

(5)图片加载不出来的几个原因:

  • 所有的请求都会被 DispatcherServlet 当作逻辑请求去做映射,由于图片属于静态资源,不应该再将其访问路径交由 DispatcherServlet 来管理,应当采用默认的方式去加载。
    在 web.xml 进行如下配置
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>
</servlet-mapping>


在 springmvc.xml 文件中添加

<!--开启静态资源访问-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>

<mvc:annotation-driven></mvc:annotation-driven>

上述两个标签须同时存在。

  • JSP 页面中<img src = "" />标签固定写死路径时应当注意的问题
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/file/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="img">
        <input type="submit" value="提交">
    </form>
    <img src="file/1.png"/>
</body>
</html>

当 "file"未加斜杠时,表示访问的当前目录下的文件,当前 upload.jsp 的访问路径为 http://localhost:8080/file,故而不加斜杠,其访问路径应当为 http://localhost:8080/file/file/1.png。
当 "file"未加斜杠时,表示访问的表示该目录为根目录的一个子目录,当前 项目的根目录为 http://localhost:8080/,故而访问路径应当为 http://localhost:8080/file/1.png。

  • idea 中 Tomcat 的配置问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ApplicationContext 可用于设置根目录,当 ApplicationContext 设置为 /springmvc 时,项目的根目录则相应的更改为 http;//localhost:8080/springmvc,若要访问 file 文件夹下的 1.png,则访问路径应当为 http;//localhost:8080/springmvc/file/1.png

1.2、多文件上传

1、uploads.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/file/uploads" method="post" enctype="multipart/form-data">
        file1:<input type="file" name="imgs"><br>
        file2:<input type="file" name="imgs"><br>
        file3:<input type="file" name="imgs"><br>
        <input type="submit" name="提交">
    </form>

    <c:forEach items="${list}" var="path">
        <img src="${path}"/>
    </c:forEach>
</body>
</html>

2、Controller

@PostMapping("/uploads")
public String uploads(@RequestParam("imgs") MultipartFile[] imgs, HttpServletRequest request){
     List<String> list = new ArrayList<>();
     for (MultipartFile img: imgs) {
         if(img.getSize() > 0){
             String path = request.getSession().getServletContext().getRealPath("/file");
             String fileName = img.getOriginalFilename();
             File pathFile = new File(path);
             if (!pathFile.exists()){
                 pathFile.mkdir();
             }

             File file = new File(path, fileName);

             try {
                 img.transferTo(file);
                 list.add("/file/" + fileName);
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
     request.setAttribute("list", list);
     return "uploads";
 }

2、文件下载

(1)download.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="/file/download?fileName=1.png">1.png</a><br>
    <a href="/file/download?fileName=2.png">2.png</a><br>
    <a href="/file/download?fileName=3.png">3.png</a><br>
</body>
</html>

Controller

@GetMapping("/download")
public void download(String fileName, HttpServletRequest request, HttpServletResponse response){
    if(fileName != null){
        String path = request.getSession().getServletContext().getRealPath("file");
        File file = new File(path, fileName);
        OutputStream outputStream = null;
        if(file.exists()) {
            // response.setContentType(MIME)的作用是使客户端浏览器区分不同种类的数据,
            // 并根据不同的MIME调用浏览器内不同的程序嵌入模块来处理相应的数据。
            // 强制下载 application/force-download
            response.setContentType("application/force-download");
            // Content-Disposition中指定的类型是文件的扩展名,
            // 并且弹出的下载对话框中的文件类型是按照文件的扩展名显示的,
            // 保存后,文件以filename的值命名,保存类型以Content中设置的为准。
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

            try {
                outputStream = response.getOutputStream();
                outputStream.write(FileUtils.readFileToByteArray(file));
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if(outputStream != null){
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值