springboot文件上传

文件上传的基本思路

上传的文件存放在硬盘上面,不直接存放到数据库中,数据库中只存放文件的相对路径。通过配置虚拟路径,允许前端访问服务器硬盘上面某个指定文件夹下面的文件。

比如,将前端传过来的文件存放在服务器上面的 D:/mm/imgs文件夹下面,同时配置虚拟路径/upLoadImg,对应D:/mm/imgs文件夹。则当想访问D:/mm/imgs文件夹下面的123.jpg时,就可以在浏览器中输入:http://ip:端口/context-path/uploadImg/123.jpg来访问。

springboot配置虚拟路径

  1. 在application.properties中配置2个自定义的属性
# 配置上传图片的虚拟路径
live.picture.url=/live_picture/**
live.picture.location=D:/rpm/imgs/
  1. 实现WebMvcConfigurer接口
/**
 * 配置虚拟路径
 */
@Configuration
public class UploadFileConfig implements WebMvcConfigurer {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${live.picture.url}")
    private String url;

    @Value("${live.picture.location}")
    private String location;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        logger.debug("url = {}, location = {}", url, location);
        registry.addResourceHandler(url).addResourceLocations("file:" + location);
    }
}

上传文件

文件怎样分布,希望文件能随机分布在某个指定文件夹下面的各个子文件夹里面,这里使用的方案是传智播客视频里面某位老师讲的一种方法。先用文件名加上uuid组成一个字符串,然后求该字符串的hashcode(1个int值),然后求这个hashcode的16进制字符串(最长是8个字符,因为1个字节是2个16进制字符),然后根据16进制字符串获取路径,假设16进制字符串位a012,则路径位a/0/1/2/。

/**
     * 根据文件名获取hashCode生成的路径
     * @param fileName 文件名
     */
    private String getHashCodePathByFileName(String fileName){
        // 生成的字符串最长也只可能是8个字符,1个字节是2个字符,比如说10对应的就是 00 00 00 0A
        String hashStr = Integer.toHexString(fileName.hashCode());
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < hashStr.length(); i++){
            sb.append(hashStr.charAt(i));
            sb.append("/");
        }
        return sb.toString();
    }

数据库中只存放文件的相对路径

/**
     * 向数据库中添加上传图片信息
     * @param basicInfoId id
     * @param fileName 文件名
     */
    private void addUploadImgBean(int basicInfoId, String fileName, String suffix) {
        UploadImgBean uploadImgBean = new UploadImgBean();
        uploadImgBean.setBasicInfoId(basicInfoId);
        uploadImgBean.setFileName(fileName + "." + suffix);
        uploadImgBean.setUrl(getHashCodePathByFileName(fileName) + fileName + "." + suffix);
        uploadImgMapper.addUploadImg(uploadImgBean);
    }

具体的上传代码

Controller中的代码

/**
     * 上传图片
     * @param basicInfoId basicInfoId
     * @param multipartFiles 上传过来的文件
     */
    @PostMapping("/live/img")
    public void upload(int basicInfoId, @RequestParam("file")MultipartFile[] multipartFiles){
        uploadImgService.uploadImgs(multipartFiles, basicInfoId);
    }

Service中的代码


@Service
public class UploadImgService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${live.picture.location}")
    private String parentDirPath;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private UploadImgMapper uploadImgMapper;

    /**
     * 上传图片
     * @param multipartFiles 前端传递过来的文件组成的数组
     */
    public void uploadImgs(MultipartFile[] multipartFiles, int basicInfoId){
        if(multipartFiles == null || multipartFiles.length == 0){
            return;
        }
        for(MultipartFile multipartFile : multipartFiles){
            if(multipartFile.isEmpty()){
                continue;
            }
            String originalFileName = multipartFile.getOriginalFilename();
            String[] strArr = originalFileName.split("\\.");
            String fileName = strArr[0] + "_" + UUIDUtils.generateUUID();
            String suffix = strArr[1];
            if(! ("jpg".equals(suffix) || "png".equals(suffix) || "gif".equals(suffix) || "jpeg".equals(suffix))){
                throw new UploadImgException(ResultEnum.UPLOAD_IMG_FORMAT_INVALID.getCode(),
                        ResultEnum.UPLOAD_IMG_FORMAT_INVALID.getMsg());
            }
            File destFile = generateFileByFileName(fileName, suffix);
            try {
                multipartFile.transferTo(destFile);//写入硬盘的文件中
                addUploadImgBean(basicInfoId, fileName, suffix);//将相对路径保存到数据库中
            } catch (IOException e) {
                e.printStackTrace();
                logger.debug(e.toString());
            }
        }
    }

    /**
     * 根据basicInfoId查询上传的图片信息
     * @param basicInfoId id
     * @return 给定basicInfoId下面的所有上传图片信息
     */
    public List<UploadImgBean> getUploadImgBean(int basicInfoId){
        return uploadImgMapper.getUploadImgBeansByBasicInfoId(basicInfoId);
    }

    /**
     * 根据图片id删除上传的图片
     * @param id 图片id
     */
    public void deleteUploadImg(int id){
        UploadImgBean uploadImgBean = uploadImgMapper.getUploadImgBeanById(id);
        //删除硬盘上面的文件
        File file = new File(this.parentDirPath + uploadImgBean.getUrl());
        file.delete();
        //删除数据库中存储的信息
        uploadImgMapper.deleteUploadImgBeanById(id);
    }

    /**
     * 向数据库中添加上传图片信息
     * @param basicInfoId id
     * @param fileName 文件名
     */
    private void addUploadImgBean(int basicInfoId, String fileName, String suffix) {
        UploadImgBean uploadImgBean = new UploadImgBean();
        uploadImgBean.setBasicInfoId(basicInfoId);
        uploadImgBean.setFileName(fileName + "." + suffix);
        uploadImgBean.setUrl(getHashCodePathByFileName(fileName) + fileName + "." + suffix);
        uploadImgMapper.addUploadImg(uploadImgBean);
    }


    /**
     * 根据文件名生成文件,文件是放在随机生成的文件夹下面的
     * @param fileName 文件名
     * @param suffix 文件后缀
     */
    private File generateFileByFileName(String fileName, String suffix){
        // 生成的字符串最长也只可能是8个字符,1个字节是2个字符,比如说10对应的就是 00 00 00 0A
        StringBuilder sb = new StringBuilder();
        sb.append(this.parentDirPath);
        sb.append(getHashCodePathByFileName(fileName));
        File dir = new File(sb.toString());
        if(! dir.exists()){
            dir.mkdirs();
        }
        File file = new File(dir, fileName + "." + suffix);
        if(! file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * 根据文件名获取hashCode生成的路径
     * @param fileName 文件名
     */
    private String getHashCodePathByFileName(String fileName){
        // 生成的字符串最长也只可能是8个字符,1个字节是2个字符,比如说10对应的就是 00 00 00 0A
        String hashStr = Integer.toHexString(fileName.hashCode());
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < hashStr.length(); i++){
            sb.append(hashStr.charAt(i));
            sb.append("/");
        }
        return sb.toString();
    }

}

你可能感兴趣的:(springboot)