当前位置:网站首页>16. 文件上传

16. 文件上传

2022-08-10 23:35:00 要学就学灰太狼


16.1 应用实例

16.1.1 需求说明

  • 演示 Spring-Boot 通过表单注册用户,并支持上传图片
  • 回顾 SpringMVC 文件上传 ==> 文章链接

16.1.2 代码实现

  1. 创建 templates/upload.html,要求头像只能选择一个,而宠物可以上传多个图片
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>upload</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF"/>
<hr/>
<div style="text-align: center">
    <h1>注册用户~</h1>
    <form action="#" method="post" th:action="@{/upload}" enctype="multipart/form-data">
        用户名:<input type="text" style="width:150px" name="name"/><br/><br/>
        电 邮:<input type="text" style="width:150px" name="email"/><br/><br/>
        年 龄:<input type="text" style="width:150px" name="age"/><br/><br/>
        职 位:<input type="text" style="width:150px" name="job"/><br/><br/>
        头 像:<input type="file" style="width:150px" name="header"><br/><br/>
        宠 物:<input type="file" style="width:150px" name="photos" multiple><br/><br/>
        <input type="submit" value="注册"/>
        <input type="reset" value="重新填写"/>
    </form>
</div>
<hr/>
<!--<img src="images/logo.png"/>-->
</body>
</html>
  1. 创建 D:\xjs_springboot\springboot-usersys\src\main\java\com\xjs\springboot\controller\UploadController.java
package com.xjs.springboot.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

/** * @Author: 谢家升 * @Version: 1.0 */
@Controller
@Slf4j
public class UploadController {
    

    //处理转发到用户注册-完成文件上传页面
    @GetMapping("/upload.html")
    public String uploadPage() {
    
        return "upload"; //thymeleaf 视图解析,转发到 templates/upload.html
    }

    //处理用户的注册请求-包括处理文件上传
    @PostMapping("/upload")
    @ResponseBody
    public String upload(@RequestParam("name") String name,
                         @RequestParam("email") String email,
                         @RequestParam("age") Integer age,
                         @RequestParam("job") String job,
                         @RequestParam("header") MultipartFile header,
                         @RequestParam("photos") MultipartFile[] photos) throws IOException {
    

        //输出获取到的信息
        log.info("上传的信息 name={} email={} age={} job={} header={} photos={}",
                name, email, age, job, header.getSize(), photos.length);

        //我们将文件保存到指定的目录,比如 D:\\temp_upload
        //1. 先将文件保存到指定的目录 比如 D:\\temp_upload
        if (!header.isEmpty()) {
     //处理头像
            //获取上传的文件的原文件名
            String originalFilename = header.getOriginalFilename();
            header.transferTo(new File("D:\\temp_upload\\" + originalFilename));
        }

        //处理宠物图片
        if (photos.length > 0) {
    
            for (MultipartFile photo : photos) {
     //遍历
                if (!photo.isEmpty()) {
    
                    String originalFilename = photo.getOriginalFilename();
                    photo.transferTo(new File("D:\\temp_upload\\" + originalFilename));
                }
            }
        }

        //==============================================

        //2. 后面再演示把文件保存到动态创建的目录中
        // 比如:类路径下的
        //(1) 先得到类路径(运行的时候)
        String path = ResourceUtils.getURL("classpath:").getPath();
        //log.info("path={}", path);

        //(2)动态创建指定的目录
        File file = new File(path + "static/images/upload/");
        if (!file.exists()) {
    //如果目录不存在 就创建
            file.mkdirs();
        }

        //处理头像
        if (!header.isEmpty()) {
    
            String originalFilename = header.getOriginalFilename();
            //这里需要指定保存文件的绝对路径,即:
            //log.info("保存文件的绝对路径={}", file.getAbsolutePath());
            // 输出即可看出路径拼接的时候是否需要加 "/"
            //保存到动态创建的目录
            header.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
        }

        //处理宠物图片
        if (photos.length > 0) {
    
            for (MultipartFile photo : photos) {
    
                String originalFilename = photo.getOriginalFilename();
                //保存到动态创建的目录
                photo.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
            }
        }

        return "注册用户成功/文件上传成功";
    }

}

在这里插入图片描述

  1. 修改 WebConfig 配置,放行/upload.html 和 /upload 请求
package com.xjs.springboot.config;

import com.xjs.springboot.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/** * @Author: 谢家升 * @Version: 1.0 */
@Configuration
public class WebConfig /*implements WebMvcConfigurer*/ {
    

    //@Override
    //public void addInterceptors(InterceptorRegistry registry) {
    
    //
    // //注册自定义拦截器LoginInterceptor
    // registry.addInterceptor(new LoginInterceptor())
    // .addPathPatterns("/**") //这里拦截所有的请求
    // .excludePathPatterns("/","/login","/images/**"); //指定要放行的,根据业务需要来添加放行的请求路径
    //
    //}

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
    

        return new WebMvcConfigurer() {
    
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
    
                //注册拦截器
                registry.addInterceptor(new LoginInterceptor())
                        .addPathPatterns("/**")
                        .excludePathPatterns("/", "/login", "/images/**", "/upload.html", "/upload");
            }
        };
    }

}

  1. 根据项目需求修改文件上传的参数,否则文件上传会抛出异常

在这里插入图片描述

  1. 创建 resources\application.yml 修改文件上传配置参数

    max-file-size 单个文件大小
    max-request-size 一次请求最大上传大小 (多个文件)

spring:
  servlet:
    multipart:
      max-file-size: 10MB # 表示单个文件上传最大 10MB
      max-request-size: 50MB # 表示一次请求上传多文件最多上传 10MB

16.1.3 完成注册用户/上传图片 -测试

16.1.3.1 启动项目

16.1.3.2 浏览器:http://localhost:8080/upload.html

16.1.3.3 页面效果

在这里插入图片描述

16.1.4 课后作业-扩展要求

  1. 解决文件覆盖问题,如果文件名相同,会出现覆盖问题,如何解决?
  2. 解决文件分目录存放问题,如果将文件都上传到一个目录下,当上传文件很多时,会造成访问文件速度变慢,因此 可以将文件上传到不同目录 比如 一天上传的文件,统一放到一个文件夹 年/月/日,比如 2022/11/11 目录
  3. 参考前面学的 java web ==> 文章链接

16.1.5 课后作业解答

  1. 生成一个唯一标识的文件名即可
String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
  • 修改 UploadController.java
package com.xjs.springboot.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

/** * @Author: 谢家升 * @Version: 1.0 */
@Controller
@Slf4j
public class UploadController {
    

    //处理转发到用户注册-完成文件上传页面
    @GetMapping("/upload.html")
    public String uploadPage() {
    
        return "upload"; //thymeleaf 视图解析,转发到 templates/upload.html
    }

    //处理用户的注册请求-包括处理文件上传
    @PostMapping("/upload")
    @ResponseBody
    public String upload(@RequestParam("name") String name,
                         @RequestParam("email") String email,
                         @RequestParam("age") Integer age,
                         @RequestParam("job") String job,
                         @RequestParam("header") MultipartFile header,
                         @RequestParam("photos") MultipartFile[] photos) throws IOException {
    

        //输出获取到的信息
        log.info("上传的信息 name={} email={} age={} job={} header={} photos={}",
                name, email, age, job, header.getSize(), photos.length);

        //我们将文件保存到指定的目录,比如 D:\\temp_upload
        //1. 先将文件保存到指定的目录 比如 D:\\temp_upload
        //if (!header.isEmpty()) { //处理头像
        // //获取上传的文件的原文件名
        // String originalFilename = header.getOriginalFilename();
        // header.transferTo(new File("D:\\temp_upload\\" + originalFilename));
        //}

        //处理宠物图片
        //if (photos.length > 0) {
    
        // for (MultipartFile photo : photos) { //遍历
        // if (!photo.isEmpty()) {
    
        // String originalFilename = photo.getOriginalFilename();
        // photo.transferTo(new File("D:\\temp_upload\\" + originalFilename));
        // }
        // }
        //}

        //==============================================

        //2. 后面再演示把文件保存到动态创建的目录中
        // 比如:类路径下的
        //(1) 先得到类路径(运行的时候)
        String path = ResourceUtils.getURL("classpath:").getPath();
        //log.info("path={}", path);

        //(2)动态创建指定的目录
        File file = new File(path + "static/images/upload/");
        if (!file.exists()) {
    //如果目录不存在 就创建
            file.mkdirs();
        }

        //处理头像
        if (!header.isEmpty()) {
    
            String originalFilename = header.getOriginalFilename();
            String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
            //这里需要指定保存文件的绝对路径,即:
            //log.info("保存文件的绝对路径={}", file.getAbsolutePath());
            // 输出即可看出路径拼接的时候是否需要加 "/"
            //保存到动态创建的目录
            //header.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
            header.transferTo(new File(file.getAbsoluteFile() + "/" + fileName));
        }

        //处理宠物图片
        if (photos.length > 0) {
    
            for (MultipartFile photo : photos) {
    
                String originalFilename = photo.getOriginalFilename();
                String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
                //保存到动态创建的目录
                //photo.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
                photo.transferTo(new File(file.getAbsoluteFile() + "/" + fileName));
            }
        }

        return "注册用户成功/文件上传成功";
    }

}

  1. 编写一个工具类,根据当前日期生成对应目录即可
  • 编写工具类 WebUtils.java
package com.xjs.springboot.utils;


import java.text.SimpleDateFormat;
import java.util.Date;

/** * @Author: 谢家升 * @Version: 1.0 */
public class WebUtils {
    

    //定义一个文件上传的路径
    public static String UPLOAD_FILE_DIRECTORY = "static/images/upload/";

    //编写方法, 根据当前日期生成目录 年/月/日
    public static String getUploadFileDirectory() {
    
        return UPLOAD_FILE_DIRECTORY + new SimpleDateFormat("yyyy/MM/dd").format(new Date());
    }

    //测试
    public static void main(String[] args) {
    

        System.out.println(WebUtils.getUploadFileDirectory());
    }

}

  • 修改 UploadController.java

在这里插入图片描述

package com.xjs.springboot.controller;

import com.xjs.springboot.utils.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

/** * @Author: 谢家升 * @Version: 1.0 */
@Controller
@Slf4j
public class UploadController {
    

    //处理转发到用户注册-完成文件上传页面
    @GetMapping("/upload.html")
    public String uploadPage() {
    
        return "upload"; //thymeleaf 视图解析,转发到 templates/upload.html
    }

    //处理用户的注册请求-包括处理文件上传
    @PostMapping("/upload")
    @ResponseBody
    public String upload(@RequestParam("name") String name,
                         @RequestParam("email") String email,
                         @RequestParam("age") Integer age,
                         @RequestParam("job") String job,
                         @RequestParam("header") MultipartFile header,
                         @RequestParam("photos") MultipartFile[] photos) throws IOException {
    

        //输出获取到的信息
        log.info("上传的信息 name={} email={} age={} job={} header={} photos={}",
                name, email, age, job, header.getSize(), photos.length);

        //我们将文件保存到指定的目录,比如 D:\\temp_upload
        //1. 先将文件保存到指定的目录 比如 D:\\temp_upload
        //if (!header.isEmpty()) { //处理头像
        // //获取上传的文件的原文件名
        // String originalFilename = header.getOriginalFilename();
        // header.transferTo(new File("D:\\temp_upload\\" + originalFilename));
        //}

        //处理宠物图片
        //if (photos.length > 0) {
    
        // for (MultipartFile photo : photos) { //遍历
        // if (!photo.isEmpty()) {
    
        // String originalFilename = photo.getOriginalFilename();
        // photo.transferTo(new File("D:\\temp_upload\\" + originalFilename));
        // }
        // }
        //}

        //==============================================

        //2. 后面再演示把文件保存到动态创建的目录中
        // 比如:类路径下的
        //(1) 先得到类路径(运行的时候)
        String path = ResourceUtils.getURL("classpath:").getPath();
        //log.info("path={}", path);

        //(2)动态创建指定的目录
        File file = new File(path + WebUtils.getUploadFileDirectory());
        if (!file.exists()) {
    //如果目录不存在 就创建
            file.mkdirs();
        }

        //处理头像
        if (!header.isEmpty()) {
    
            String originalFilename = header.getOriginalFilename();
            String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
            //这里需要指定保存文件的绝对路径,即:
            //log.info("保存文件的绝对路径={}", file.getAbsolutePath());
            // 输出即可看出路径拼接的时候是否需要加 "/"
            //保存到动态创建的目录
            //header.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
            header.transferTo(new File(file.getAbsoluteFile() + "/" + fileName));
        }

        //处理宠物图片
        if (photos.length > 0) {
    
            for (MultipartFile photo : photos) {
    
                String originalFilename = photo.getOriginalFilename();
                String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
                //保存到动态创建的目录
                //photo.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
                photo.transferTo(new File(file.getAbsoluteFile() + "/" + fileName));
            }
        }

        return "注册用户成功/文件上传成功";
    }

}

在这里插入图片描述

原网站

版权声明
本文为[要学就学灰太狼]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_60766221/article/details/126231323