[SpringMVC 입문부터 실전 튜토리얼까지] Chapter 4 SpringMVC 업로드 및 다운로드

4. SpringMVC 업로드 및 다운로드

    파일 업로드: IO를 통해 파일을 복사하고 로컬 파일을 서버에 복사하는 것이 본질입니다.
    
    파일 다운로드: 본질은 IO를 통해 파일을 복사하고 서버 측 파일을 로컬에 복사하는 것입니다.
    
    Spring MVC 프레임워크의 파일 업로드는 commons-fileupload 구성 요소를 기반으로 하며, 이 구성 요소에 추가 패키지가 만들어져 파일 업로드의 코드 구현을 단순화하고 다른 업로드 구성 요소의 프로그래밍 차이를 제거합니다.

4.1 파일 업로드 jar 패키지 가져오기

방법 1: jar 패키지 가져오기

 방법 2: maven 종속성 구성

<dependencies>
    <!-- spring核心包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springbean包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springcontext包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- spring表达式包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springAOP包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springAspects包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- spring对web的支持 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- springwebMVC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>

    <!-- 配置javaweb环境 -->
    <!-- servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
        <scope>provided</scope>
    </dependency>
    <!-- jstl -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <!-- 上传组件包 -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>
</dependencies>

4.2 구성

  • SpringMVC는 플러그 앤 플레이 MultipartResolver를 통해 구현되는 파일 업로드를 직접 지원합니다.

  • SpringMVC는 Commons FileUpload 기술인 CommonsMultipartResovler로 구현 클래스를 구현합니다.

  • MultipartResovler는 SpringMVC에 기본적으로 설치되어 있지 않기 때문에 기본적으로 파일 업로드를 처리할 수 없으며, 이를 사용하려면 CommonsMultipartResovler를 구성해야 합니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- springmvc的注解式开发 -->
    <!-- 开启组件扫描 -->
    <context:component-scan base-package="com.newcapec.controller"/>

    <!-- MVC注解驱动 -->
    <mvc:annotation-driven/>

    <!-- 配置视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 配置文件上传解析器 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 文件上传的属性设置 -->
        <!-- 设置上传文件的大小: 文件的总字节数 -->
        <!-- 
 			1KB = 1024B
			1MB = 1024KB
			1GB = 1024MB
			1TB = 1024GB
			...
		-->
        <property name="maxUploadSize" value="104857600"/>
        <!-- 设置上传的字符编码 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 设置缓存大小 -->
        <property name="maxInMemorySize" value="10240"/>
    </bean>
</beans>

4.3 단일 파일 업로드

4.3.1 페이지

index.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center;">
        <h1>首页</h1>
        <p><a href="views/upload.jsp">文件上传</a></p>
        <p><a href="views/uploads.jsp">批量上传</a></p>
        <p><a href="views/show.jsp">文件展示</a></p>
        <p><a href="views/download.jsp">文件下载</a></p>
    </div>
</body>
</html>

성공.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center;">
        <h1>上传成功!!!</h1>
    </div>
</body>
</html>

업로드.jsp:

  • 양식 제출 유형이 enctype="multipart/form-data"로 변경되었습니다.

  • 제출 방법은 게시물 요청, method="post"입니다.

  • type="file"의 입력 양식 요소를 양식에 추가하여 업로드할 파일을 선택하십시오.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>文件上传</h1>
        <!--
        在前端或页面中需要注意的:
        1.文件上传时提交的请求方法必须为post
        2.在form标签中enctype
        	enctype="application/x-www-form-urlencoded"为默认值:将数据转换为key/value格式,用于普通数据的提交
        	上传时需要修改enctype为enctype="multipart/form-data": 告知服务器请求中包含二进制的数据(文件)
        3.使用上传组件(上传表单元素) <input type="file">
        -->
        <form action="upload.do" method="post" enctype="multipart/form-data">
            <p>请选择文件:<input type="file" name="file"></p>
            <p><button>上传</button></p>
        </form>
    </div>
</body>
</html>

4.3.2 컨트롤러

업로드된 파일을 수신할 컨트롤러의 메소드에 MultipartFile 유형의 매개변수를 추가하십시오.

@Controller
public class UploadController {

    /**
     * 文件上传: 将本地文件传输至服务端
     * 在springmvc中通过MultipartFile对象来接收上传的文件
     * MultipartFile对象就是通过文件上传解析器创建的
     */
    @RequestMapping("/upload.do")
    public String upload(MultipartFile file, HttpServletRequest request) throws IOException {
        /**
         * 处理上传文件:
         * 1.获取文件的基本信息
         * 2.指定文件的保存目录
         * 3.防止文件名称重复
         * 4.复制文件
         */
        //获取文件大小
        long fileSize = file.getSize();
        //获取文件名称
        String fileName = file.getOriginalFilename();
        System.out.println(fileSize);
        System.out.println(fileName);

        /**
         * 2.指定文件的保存目录
         * 第一种:当前项目目录下(不是工作空间中,而是项目发布后的目录)
         *      优点:属于项目内部资源,方便访问
         *      问题:文件在项目中,如果文件数据量大,不利于项目迁移
         * 第二种:服务器的文件系统中的目录
         *      优点:项目资源与上传文件分离
         *      问题:无法直接访问,需要配置虚拟目录,或搭建文件服务器
         */
        String rootPath = request.getServletContext().getRealPath("/upload");
        // String rootPath = "c:/upload";
        /**
         * 3.防止文件名称重复
         * 使用新建目录,分开存放文件
         * 使用UUID来生成新的文件名称
         */
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy");
        SimpleDateFormat sdf2 = new SimpleDateFormat("MM");
        Date today = new Date();
        String year = sdf1.format(today);
        String month = sdf2.format(today);

        File dir = new File(rootPath + "/" + year + "/" + month);
        if(!dir.exists()){
            dir.mkdirs();
        }

        String newName = UUID.randomUUID().toString().replace("-","") +
            fileName.substring(fileName.lastIndexOf("."));

        //目标文件
        File resultFile = new File(dir.getAbsolutePath() + "/" + newName);

        //4.文件传输
        file.transferTo(resultFile);
        System.out.println("文件上传成功...");
        return "success";
    }
}

MultipartFile 클래스의 일반적인 메서드는 다음과 같습니다.

방법 효과
getOriginalFilename() 업로드된 파일의 원래 이름을 가져옵니다.
getSize() 파일의 바이트 크기, 단위 바이트 가져오기
transferTo(파일 목적지) i/o 스트림을 통해 지정된 위치에 파일 저장
getName() 형식에서 파일 구성 요소의 이름을 가져옵니다.
getContentType() 파일 MIME 유형 가져오기
getInputStream() 파일 스트림 가져오기
비었다() 비어 있습니까?

업로드된 파일 처리:

  • 파일 저장 디렉토리

    • 첫 번째 유형: 현재 프로젝트 디렉토리 아래(작업 공간이 아니라 프로젝트가 릴리스된 후 디렉토리). 장점: 프로젝트의 내부 리소스에 속하며 액세스하기 쉽습니다 문제: 파일이 프로젝트에 있는 경우 파일에 많은 양의 데이터가 있으면 프로젝트 마이그레이션에 도움이 되지 않습니다.

    • 두 번째 유형: 서버의 파일 시스템에 있는 디렉토리. 장점: 프로젝트 리소스와 업로드된 파일 분리 문제: 직접 액세스 불가, 가상 디렉터리 구성 또는 파일 서버 구축 필요

  • 중복 파일 이름을 방지합니다.

    • 새 디렉토리를 사용하여 파일을 별도로 저장하십시오.

    • UUID를 사용하여 새 파일 이름을 생성하십시오.

4.4 일괄 업로드

업로드.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>批量上传</h1>
        <form action="uploadBatch.do" method="post" enctype="multipart/form-data">
            <p>请选择文件1:<input type="file" name="file"></p>
            <p>请选择文件2:<input type="file" name="file"></p>
            <p>请选择文件3:<input type="file" name="file"></p>
            <p><button>上传</button></p>
        </form>
    </div>
</body>
</html>

업로드된 파일을 수신하기 위한 매개변수는 MultipartFile 유형의 배열입니다.

/**
  * 批量上传
  * 将MultipartFile对象定义为数组类型
  */
@RequestMapping("/uploadBatch.do")
public String uploadBatch(MultipartFile[] file) throws IOException {
    for (MultipartFile multipartFile : file) {
        multipartFile.transferTo(new File("c:/upload/" +  multipartFile.getOriginalFilename()));
    }
    System.out.println("批量上传成功...");
    return "success";
}

4.5 다운로드

다운로드.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <a href="download.do?name=a.jpg">图片1</a>
        <a href="download.do?name=b.jpg">图片2</a>
        <a href="download.do?name=c.jpg">图片3</a>
        <a href="download.do?name=中文.txt">文件</a>
    </div>
</body>
</html>

응답 헤더를 설정하기만 하면 됩니다.

@Controller
public class DownloadController {

    /**
     * 文件下载:将服务端的文件传输至客户端
     * 页面无需跳转,需要设置下载响应头
     */
    @RequestMapping("/download.do")
    public void download(String name, HttpServletResponse response) throws Exception {
        /**
         * 设置下载响应头
         * 1.content-disposition对应的值为attachment
         * 告知浏览器客户端,响应为回传文件(附件)
         * 2.设置下载时文件名称
         * "attachment;fileName="+name
         * 3.文件名称中文处理
         * 使用URLEncoder对象进行转码
         */
        // response.addHeader("content-disposition", "attachment");
        // response.addHeader("content-disposition", "attachment;fileName="+name);
        String filename = URLEncoder.encode(name,"UTF-8");
        response.addHeader("content-disposition", "attachment;fileName="+filename);

        //通过流进行文件传输
        FileInputStream inputStream = new FileInputStream("c:/upload/" + name);
        OutputStream outputStream = response.getOutputStream();

        byte[] buffer = new byte[1024];
        while(inputStream.read(buffer) != -1) {
            outputStream.write(buffer);
        }

        outputStream.flush();
        inputStream.close();
        outputStream.close();
    }
}

4.6 리소스 로딩

show.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center;">
        <h1>图片展示</h1>
        <!--
			<p><img src="c:/upload/a.jpg"></p>
			错误写法
		-->
        <p><img src="upload/a.jpg"></p>
        <p><img src="/up/a.jpg"></p>
        <p><img src="/up/b.jpg"></p>
        <p><img src="/up/c.jpg"></p>
    </div>
</body>
</html>

실제 디렉터리(하드 디스크의 실제 디렉터리)는 페이지에서 액세스할 수 없으므로 서버에서 해당 가상 디렉터리를 구성해야 합니다.

4.6.1 Eclipse에서 구성

1. 서비스 목록에서 tomcat을 두 번 클릭합니다.

 2. tomcat이 구성한 모듈을 엽니다.

 3. 웹 모듈에서 가상 경로를 구성합니다.

4.6.2 IDEA에서 구성

1. 메뉴 모음에서 실행 메뉴를 찾고 구성 편집을 선택합니다.

 2. 배포 탭을 선택하고 더하기 기호를 클릭한 다음 외부 소스를 선택합니다.

 3. 가상 경로에 해당하는 물리적 디렉토리를 선택합니다.

 4. 애플리케이션 컨텍스트에서 가상 경로를 구성합니다.

4.6.3 tomcat에서 설정

구성 디렉토리 conf의 server.xml 파일에서 <Host> 태그를 찾고 다음 코드를 추가하십시오. docBase는 실제 디렉토리이고 path는 가상 경로입니다.

<Context docBase="c:\upload" path="/up" reloadable="true"/>

추천

출처blog.csdn.net/ligonglanyuan/article/details/125167791