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, 863263957@qq.com 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,这意味着文件将立即写入磁盘。

 微信公众号

 

 

posted @ 2020-01-14 09:49  盲目的拾荒者  阅读(427)  评论(0编辑  收藏  举报