32.再谈SpringBoot文件上传

  • Controller配置    
以具体代码为通过时间为文件夹分类上传的文件
/**

* @Title: upload
* @Description: 上传图片
* @param file
* @throws IOException    
* @return String    
* @throws
*/
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public ResultBean<String> upload(@RequestParam(value = "file", required = false) MultipartFile file)
throws IOException {


byte[] bytes = file.getBytes();
String originalFilename = file.getOriginalFilename();
int indexOf = originalFilename.indexOf(".");
String extend = originalFilename.substring(indexOf);
String format = DateUtils.format(new Date(), DateUtils.YYYYMMDD);
String nowFileName = DateUtils.format(new Date(), DateUtils.YYYYMMDDHHMMSS);
String strPath = "upload/" + format;
File path = new File(strPath);
if (!path.exists()) {
path.mkdirs();
}
// 这样默认上传文件就放在当前 项目路径下
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(strPath).append("/").append(nowFileName).append(extend);
File name = new File(stringBuilder.toString());
FileCopyUtils.copy(bytes, name);
ResultBean<String> resultBean = new ResultBean<String>();
resultBean.setData(stringBuilder.toString());
return resultBean;
}

         (上图为最后上传的效果)

  • application.properties

###########springboot文件上传
#spring.http.multipart.location=upload
#最大文件上传
spring.http.multipart.max-file-size=1MB
#最大请求
spring.http.multipart.max-request-size=100MB
  • 上传出错捕获
以下主要是,针对异步请求上传出错的捕获,捕获之后通过Redis发布与订阅者模式,将错误日志异步发送给订阅者,然后存储到elasticsearch中(以下代码中没有涉及)
  • package org.niugang.exception;

    import java.io.IOException;
    import java.util.Date;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.tomcat.util.http.fileupload.FileUploadBase.FileSizeLimitExceededException;
    import org.niugang.bean.CustomErrorType;
    import org.niugang.constant.LogType;
    import org.niugang.utils.DateUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.security.access.AccessDeniedException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartException;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
    import com.alibaba.fastjson.JSONObject;

    /**
     * 也可以使用aop监控  ControllerAop.java
     * @Description:异步调用统一处理异常类
     * @Project:boot-sis
     * @File:ControllerAdviceException.java
     * @Package:org.niugang.exception
     * @Date:2018年7月2日上午9:49:30
     * @author:niugang
     * @Copyright (c) 2018, [email protected] All Rights Reserved.
     *
     */
    @ControllerAdvice
    public class ControllerAdviceException extends ResponseEntityExceptionHandler {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @ExceptionHandler({ Exception.class })
    @ResponseBody
    ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex, HttpServletResponse response)
    throws ServletException, IOException {
    HttpStatus status = getStatus(request);
    String message = "";
    // 如果异常
    if (ex instanceof AccessDeniedException) {
    String header = request.getHeader("x-requested-with");
    if (header != null && header.equals("XMLHttpRequest")) {
    // throw new RuntimeException("暂无权限");
    // 异步清楚不抛异常,才能继续往下走
    } else {
    request.getRequestDispatcher("/exception/403").forward(request, response);
    }


    }
    // 文件上传  文件上传出错代码捕获
    if (ex instanceof MultipartException) {
    MultipartException e = (MultipartException) ex;
    FileSizeLimitExceededException ee = (FileSizeLimitExceededException) e.getCause().getCause();
    String acutalSize = "实际为:" + (ee.getActualSize() / 1024) + "KB";
    message = "允许上传为:" + (ee.getPermittedSize() / 1024) + "kb" + acutalSize;
    }

    CustomErrorType cx = createExceptionAndSendMessage(status, request, ex);
    if (StringUtils.isNotBlank(message)) {
    cx.setMessage(message);
    }
    return new ResponseEntity<>(cx, status);

    }


    /**

    * @Title: createExceptionAndSendMessage
    * @Description: 封装异常并发送消息
    * @param status
    * @param request
    * @param ex
    * @return    
    * @return CustomErrorType    
    * @throws
    */
    public CustomErrorType createExceptionAndSendMessage(HttpStatus status, HttpServletRequest request, Throwable ex) {
    CustomErrorType customErrorType = new CustomErrorType();
    customErrorType.setStatus(status.value());
    customErrorType.setMessage(ex.getLocalizedMessage());
    customErrorType.setTimestamp(System.currentTimeMillis());
    customErrorType.setError(status.getReasonPhrase());
    // customErrorType.setException(ex.getCause().getCause().getMessage());
    messageQueue(customErrorType, request);
    return customErrorType;
    }


    private void messageQueue(CustomErrorType customErrorType, HttpServletRequest request) {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("value", customErrorType.getMessage());
    jsonObject.put("type", LogType.ERROR_LOG);
    jsonObject.put("ip", getIpAddr(request));
    jsonObject.put("port", request.getRemotePort());
    jsonObject.put("time", DateUtils.format(new Date(), DateUtils.YYYY_MM_DD_HH_MM_SS));
    if (StringUtils.isNotBlank(customErrorType.getMessage())) {
    redisTemplate.convertAndSend("log_queue", jsonObject.toJSONString());
    }


    }


    private HttpStatus getStatus(HttpServletRequest request) {
    Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
    if (statusCode == null) {
    return HttpStatus.INTERNAL_SERVER_ERROR;
    }
    return HttpStatus.valueOf(statusCode);
    }


    public static String getIpAddr(HttpServletRequest request) {

    String ip = request.getHeader("x-forwarded-for");
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getRemoteAddr();
    }
    return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }
    }
  • 源码配置解析

    

  • location specifies the directory where files will be stored. The default is "". A common value is to use the system's temporary directory, which can be obtained.

     //location指定存储文件的目录。默认的是“”。一个常见的值是使用系统的临时目录,该目录可以获得。

     //如果指定了locationname其实在默认tomcat记录路径上存储上传的文件,不易查找,建议上传专门指定文件上传目录

  • max-file-size specifies the maximum size permitted for uploaded files. The default is 1MB.
    //指定上传文件允许的最大大小。默认是1 mb。
  • max-request-size specifies the maximum size allowed for multipart/form-data requests. The default is 10MB
//指定允许多部分/表单数据请求的最大大小。默认值是10 mb
  • file-size-threshold specifies the size threshold after which files will be written to disk. Default is 0, which means that the file will be written to disk immediately. 
//指定文件写入磁盘后的大小阈值。默认值是0,这意味着文件将立即写入磁盘。


猜你喜欢

转载自blog.csdn.net/niugang0920/article/details/80947057