后端文件上传逻辑详解

路径问题

  • 因为开发时和部署时的系统不同,所以文件路径应该是可装配的,最好写在配置文件中,通过**@Value**注解来动态获取。
//配置文件
community.path.domain=http://localhost:8080
community.path.upload=d:/work/data/upload
//控制层代码  用来获取配置文件中的路径
@Value("${community.path.upload}")
    private String uploadPath;
    @Value("${community.path.domain}")
    private String domain;
    @Value("${server.servlet.context-path}")
    private String contextPath;

上传业务逻辑

  1. 通过MultipartFile来接收文件,如果是多个文件则以数组的形式接收

    @PostMapping(path = "/upload")
    public String uploadHeader(MultipartFile headerImage, Model model)
    
  2. 判断文件是否为空,不为空才执行该方法

  3. 通过参数获得该文件的名字

String fileName = headerImage.getOriginalFilename();
  1. 通过文件名字来截取文件的后缀
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
  1. 因为不同用户的文件名可能相同,所以要再生成随机的文件名来防止文件覆盖
fileName =  CommunityUtil.generateUUID()+suffix; //注:随便一个生成uuid的工具类即可
  1. 确定文件存放的路径
  File dest = new File(uploadPath+"/"+fileName);
  1. 将文件上传到目标路径
 try {//自带的上传文件的接口
        headerImage.transferTo(dest);
    } catch (IOException e) {
throw new RuntimeException("上传文件失败",e);
    }
  1. 更新数据库中相关的数据(本例中是用户的头像路径)
   User user = hostHolder.getUser();
    String headerUrl = domain + contextPath + "/user/header/"+ fileName;
    userService.updateHeader(user.getId(),headerUrl);

访问/获取业务逻辑

  1. 本方法的路径不能乱写,要与上面第8个配置的路径相同
  @RequestMapping(path = "/header/{fileName}", method = RequestMethod.GET)
    public void getHeader(@PathVariable("fileName") String fileName, HttpServletResponse response)
  1. 找到服务器存放路径,获得文件后缀
  fileName = uploadPath + "/" + fileName;
  String suffix = fileName.substring(fileName.lastIndexOf("."));
  1. 响应图片,修改response返回格式
//该内容类型的意思是访问图片      
response.setContentType("image/" + suffix);
  1. response读取文件
  try (
                FileInputStream fis = new FileInputStream(fileName);
                OutputStream os = response.getOutputStream();
        ) {
            byte[] buffer = new byte[1024];
            int b = 0;
            while ((b = fis.read(buffer)) != -1) {
                os.write(buffer, 0, b);
            }
        } catch (IOException e) {
            log.error("读取头像失败: " + e.getMessage());
        }
  • 注:上面的第一个圆括号是java7的特性,可以自动关闭流

上传完整代码

@PostMapping(path = "/upload")
public String uploadHeader(MultipartFile headerImage, Model model){
        if(headerImage == null) {
            model.addAttribute("error","您还没有选择图片");
            return "/site/setting";
        }

    String fileName = headerImage.getOriginalFilename();
    String suffix = fileName.substring(fileName.lastIndexOf("."));
if(StringUtils.isBlank(suffix)){
    model.addAttribute("error","文件的格式不正确");
    return "/site/setting";
}
fileName =  CommunityUtil.generateUUID()+suffix;
    File dest = new File(uploadPath+"/"+fileName);
    try {
        headerImage.transferTo(dest);
    } catch (IOException e) {
log.error("上传文件失败");
throw new RuntimeException("上传文件失败",e);
    }
    //更新当前用户头像的路径
    User user = hostHolder.getUser();
    String headerUrl = domain + contextPath + "/user/header/"+ fileName;
    userService.updateHeader(user.getId(),headerUrl);
    return "redirect:/index";
}

访问完整代码

 @RequestMapping(path = "/header/{fileName}", method = RequestMethod.GET)
    public void getHeader(@PathVariable("fileName") String fileName, HttpServletResponse response) {
        // 服务器存放路径
        fileName = uploadPath + "/" + fileName;
        // 文件后缀
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        // 响应图片
        response.setContentType("image/" + suffix);
        try (
                FileInputStream fis = new FileInputStream(fileName);
                OutputStream os = response.getOutputStream();
        ) {
            byte[] buffer = new byte[1024];
            int b = 0;
            while ((b = fis.read(buffer)) != -1) {
                os.write(buffer, 0, b);
            }
        } catch (IOException e) {
            log.error("读取头像失败: " + e.getMessage());
        }
    }

补充

  1. 在读取文件返回那块,有已经写好的方法可以直接调用,在hutool依赖中
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.3</version>
        </dependency>
  • 调用的代码
  //注:该内容类型的意思是下载而非访问
  response.setContentType("application/octet-stream");
   byte[] bytes=FileUtil.readBytes(basePath+fileName);
   os=response.getOutputStream();
   os.write(bytes);
   os.flush();
   os.close();
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值