SpringBooot文件上传

本文介绍了如何使用SpringMVC进行文件上传,包括通用上传请求方法、FileUploadUtils工具类的使用,以及文件名处理和URL生成的过程。重点在于处理文件路径、大小限制和MIME类型验证。

代码

上传文件时请求的方法

/**
* 通用上传请求
*/
@PostMapping("/upload")
public ResultJson uploadFile(MultipartFile file) throws Exception {
  try {
      // 上传文件路径
      //得到的是D:/code/uploadPath/upload
      String filePath = NiuaConfig.getUploadPath();

      //FileUploadUtils是上传的工具类
      //filePath, file两个参数分别为磁盘或者服务器上的绝对路径既是上传路径 和 上传的二进制文件
      //得到的fileName为/profile开头的路径/profile/upload/2022/07/01
      String fileName = FileUploadUtils.upload(filePath, file);

      //serverConfig.getUrl()是用于获取localhost:8080这些地址的
      //再加上fileName得到url
      //从而得到可以直接用url访问的资源路径
      // http://127.0.0.1:9527/profile/upload/2022/07/01/4d9738e4-4e38-4a76-b3c3-6ee1ab026269.png
      String url = serverConfig.getUrl() + fileName;
      Map<String, String> prams = new HashMap<String, String>();
      prams.put("fileName", fileName);
      prams.put("url", url);
      return ResultJson.ok(prams);
  } catch (Exception e) {
      return ResultJson.failure(ResultCode.BAD_REQUEST, e.getMessage());
  }
}

上传工具类

public class FileUploadUtils {
   /**
    * 默认大小 50M
    */
   public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;

   /**
    * 默认的文件名最大长度 100
    */
   public static final int DEFAULT_FILE_NAME_LENGTH = 100;

   /**
    * 默认上传的地址
    */
   private static String defaultBaseDir = NiuaConfig.getProfile();

   public static void setDefaultBaseDir(String defaultBaseDir)
   {
       FileUploadUtils.defaultBaseDir = defaultBaseDir;
   }

   public static String getDefaultBaseDir()
   {
       return defaultBaseDir;
   }

   /**
    * 以默认配置进行文件上传
    *
    * @param file 上传的文件
    * @return 文件名称
    * @throws Exception
    */
   public static final String upload(MultipartFile file) throws IOException
   {
       try
       {
           return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
       }
       catch (Exception e)
       {
           throw new IOException(e.getMessage(), e);
       }
   }

   /**
    * 根据文件路径上传
    *
    * @param baseDir 相对应用的基目录
    * @param file 上传的文件
    * @return 文件名称
    * @throws IOException
    */
   public static final String upload(String baseDir, MultipartFile file) throws IOException
   {
       //baseDir文件的上传路径
       //file要上传的二进制文件
       //DEFAULT_ALLOWED_EXTENSION 默认允许的上传的扩展名
       try
       {
           return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
       }
       catch (Exception e)
       {
           throw new IOException(e.getMessage(), e);
       }
   }

   /**
    * 文件上传
    *
    * @param baseDir 相对应用的基目录
    * @param file 上传的文件
    * @param allowedExtension 上传文件类型
    * @return 返回上传成功的文件名
    * @throws FileSizeLimitExceededException 如果超出最大大小
    * @throws FileNameLengthLimitExceededException 文件名太长
    * @throws IOException 比如读写文件出错时
    * @throws InvalidExtensionException 文件校验异常
    */
   public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
           throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
           InvalidExtensionException
   {
       //fileNamelength上传的文件名的长度,不能过长
       int fileNamelength = file.getOriginalFilename().length();
       if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
       {
           throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
       }
       //判断文件的扩展名是不是DEFAULT_ALLOWED_EXTENSION中定义的默认允许的上传的扩展名
       //不是就会抛异常
       assertAllowed(file, allowedExtension);
       //做出一个文件的相对路径名
       //相对于传入的参数baseDir的绝对路径
       String fileName = extractFilename(file);
       //根据路径检查是否有相关文件夹,没有就创建
       File desc = getAbsoluteFile(baseDir, fileName);
       //将文件写入那个服务器中的绝对路径中
       file.transferTo(desc);

       //返回文件上传后经过springmvc映射后的地址
       //既是将profile: D:/code/uploadPath/
       //映射成/profile
       //从而可以直接用url访问http://127.0.0.1:9527/profile/upload/2022/07/01/4d9738e4-4e38-4a76-b3c3-6ee1ab026269.png
       String pathFileName = getPathFileName(baseDir, fileName);
       return pathFileName;
   }

   /**
    * 编码文件名
    */
   public static final String extractFilename(MultipartFile file)
   {
       String fileName = file.getOriginalFilename();
       //获取文件的扩展名
       String extension = getExtension(file);
       //fileName文件的路径名
       //IdUtils.fastUUID()将文件名化为fastUUID()这种类似乱码形式的名字
       //DateUtils.datePath()将日期年月日化为路径
       fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
       return fileName;
   }

   private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
   {
       File desc = new File(uploadDir + File.separator + fileName);

       if (!desc.getParentFile().exists())
       {
           desc.getParentFile().mkdirs();
       }
       if (!desc.exists())
       {
           desc.createNewFile();
       }
       return desc;
   }

   private static final String getPathFileName(String uploadDir, String fileName) throws IOException
   {
       int dirLastIndex = NiuaConfig.getProfile().length();
       String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
       //Constants.RESOURCE_PREFIX的值为/profile
       String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
       return pathFileName;
   }

   /**
    * 文件大小校验
    *
    * @param file 上传的文件
    * @return
    * @throws FileSizeLimitExceededException 如果超出最大大小
    * @throws InvalidExtensionException
    */
   public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
           throws FileSizeLimitExceededException, InvalidExtensionException
   {
       long size = file.getSize();
       if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
       {
           throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
       }

       String fileName = file.getOriginalFilename();
       String extension = getExtension(file);
       if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
       {
           if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
           {
               throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                       fileName);
           }
           else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
           {
               throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                       fileName);
           }
           else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
           {
               throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                       fileName);
           }
           else
           {
               throw new InvalidExtensionException(allowedExtension, extension, fileName);
           }
       }

   }

   /**
    * 判断MIME类型是否是允许的MIME类型
    *
    * @param extension
    * @param allowedExtension
    * @return
    */
   public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
   {
       for (String str : allowedExtension)
       {
           if (str.equalsIgnoreCase(extension))
           {
               return true;
           }
       }
       return false;
   }

   /**
    * 获取文件名的后缀
    *
    * @param file 表单文件
    * @return 后缀名
    */
   public static final String getExtension(MultipartFile file)
   {
       String extension = FilenameUtils.getExtension(file.getOriginalFilename());
       if (StringUtils.isEmpty(extension))
       {
           extension = MimeTypeUtils.getExtension(file.getContentType());
       }
       return extension;
   }
}

代码分析

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值