spring boot项目同时传递参数和文件的多种方式代码演示
作者:kangaroo.
在开发接口中,遇到了需要同时接收参数和文件的情况,可以有多种方式实现文件+参数的接收,这里基于spring boot 3 + vue 3 + axios,做一个简单的代码演示。
1 简单参数 + 文件参数
参数较少时,比较方便,直接参数接受即可
1.1 后端接口
@RestController @RequestMapping("/param") @Validated public class FileParamController extends BaseController { /** * 简单参数 * * @param test1 * @param test2 * @param file * @return */ @PostMapping("/file-simple-param") public Map<String, Object> fileAndSimpleParam(@RequestParam @NotBlank String test1, @RequestParam @NotBlank String test2, @RequestParam MultipartFile file) { Map<String, Object> objectMap = new HashMap<>(); objectMap.put("test1", test1); objectMap.put("test2", test2); objectMap.put("fileName", file.getOriginalFilename()); return objectMap; } }
1.2 前端请求
const fileAndSimpleParamFuc = (methodParam: { file: string | Blob }) => { let formData = new FormData() formData.append('test1', 'test1') formData.append('test2', 'test2') formData.append('file', methodParam.file) fileAndSimpleParam(formData).then(resp => { console.log(resp) }) }
fileAndSimpleParam 为封装的api请求方法,可查看下文的 param.ts
2 简单参数转JavaBean + 文件参数
将各个参数封装到一个JavaBean中接收,同时接收文件参数,此时JavaBean参数不加任何注解,不支持接收List参数
2.1 后端接口
@RestController @RequestMapping("/param") @Validated public class FileParamController extends BaseController { /** * 简单参数转JavaBean接收,不支持如:LIst<xxx> 这样的属性 * * @param bean * @param file * @return */ @PostMapping("/file-simple-bean") public SimpleBean fileAndSimpleJavaBean(@Validated SimpleBean bean, @RequestParam MultipartFile file) { bean.setFileName(file.getOriginalFilename()); return bean; } }
SimpleBean.java
@Data public class SimpleBean { @NotBlank private String test1; @NotBlank private String test2; @Null(message = "The fileName is not support to be used") private String fileName; }
2.2 前端请求
const fileAndSimpleJavaBeanFuc = (methodParam: { file: string | Blob }) => { let formData = new FormData() formData.append('test1', 'test1') formData.append('test2', 'test2') formData.append('file', methodParam.file) fileAndSimpleJavaBean(formData).then(resp => { console.log(resp) }) }
fileAndSimpleJavaBean 为封装的api请求方法,可查看下文的 param.ts
3 简单参数转String + 文件参数
在这种接收方式中,使用String来接收参数,在使用工具(如fastjson)手动转为JavaBean,支持接收List参数,但是需要自行校验参数是否满足要求
3.1 后端接口
@RestController @RequestMapping("/param") @Validated public class FileParamController extends BaseController { /** * 参数转字符串接收,支持复杂参数属性,如:List<xxx> * * @param bean * @param file * @return */ @PostMapping("/file-and-json") public SimpleBean fileAndJsonJavaBean(String bean, @RequestParam MultipartFile file) { SimpleBean simpleBean = JSON.parseObject(bean, SimpleBean.class); //自定义参数校验 List<String> valid = ValidatorUtils.validFast(simpleBean); if (!valid.isEmpty()) { throw new FailException(String.join(",", valid)); } simpleBean.setFileName(file.getOriginalFilename()); return simpleBean; } }
SimpleBean.java
@Data public class SimpleBean { @NotBlank private String test1; @NotBlank private String test2; private List<ParamBO> params; @Null(message = "The fileName is not support to be used") private String fileName; }
ValidatorUtils.java
借助spring的参数校验做自定义调用
public class ValidatorUtils { private static final Validator VALIDATOR_FAST = Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator(); private static final Validator VALIDATOR_ALL = Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator(); private ValidatorUtils(){} /** * 参数校验,遇到第一个不合法的字段直接返回不合法字段,后续字段不再校验 * * @param object * @return * @param <T> */ public static <T> List<String> validFast(T object, Class<?>... groups){ return valid(VALIDATOR_FAST, object, groups); } /** * 校验所有字段并返回不合法字段 * * @param object * @return * @param <T> */ public static <T> List<String> validAll(T object, Class<?>... groups){ return valid(VALIDATOR_ALL, object, groups); } private static <T> List<String> valid(Validator validator, T object, Class<?>... groups){ Set<ConstraintViolation<T>> errors = validator.validate(object, groups); return errors.stream().map(ConstraintViolation::getMessage).toList(); } }
3.2 前端请求
const fileAndJsonStringToJavaBeanFuc = (methodParam: { file: string | Blob }) => { let paramList = [] for (let i = 0; i < 3; i++) { let param = { username: '参数' + i, data: '参数值' + i } paramList.push(param) } let data = { test1: 'test1', test2: 'test2', params: paramList } let formData = new FormData() formData.append('bean', JSON.stringify(data)) formData.append('file', methodParam.file) fileAndJsonStringToJavaBean(formData).then(resp => { console.log(resp) }) }
fileAndJsonStringToJavaBean 为封装的api请求方法,可查看下文的 param.ts
4 文件放入JavaBean接收
将文件作为JavaBean的属性,随参数一起接收
4.1 后端接口
@RestController @RequestMapping("/param") @Validated public class FileParamController extends BaseController { /** * 文件放入JavaBean一起提交 * * @param bean * @return */ @PostMapping(value = "/file-in-bean") public String fileInJavaBean(@Validated FileInBeanBO bean) { bean.setFileName(bean.getFile().getOriginalFilename()); return bean.getFile().getOriginalFilename(); } }
FileInBeanBO.java
@Data public class SimpleBean { @NotBlank private String test1; @NotBlank private String test2; @Null(message = "The fileName is not support to be used") private String fileName; private MultipartFile file; }
4.2 前端请求
此处需要特别注意,需要修改Content-Type
const fileInJavaBeanFuc = (methodParam: { file: string | Blob }) => { let formData = new FormData() formData.append('test1', 'test1') formData.append('test2', 'test2') formData.append('file', methodParam.file) fileInJavaBean(formData).then(resp => { console.log(resp) }) }
fileInJavaBean 为封装的api请求方法,可查看下文的 param.ts
5 文件和参数分别接收,@RequestPart注解
使用@RequestPart注解,实现参数与文件分别接收,应该来说是最优解,优先推荐
5.1 后端接口
@RestController @RequestMapping("/param") @Validated public class FileParamController extends BaseController { /** * 参数与文件分开接收,支持复杂参数属性,如:List<xxx> * * @param bean * @param file * @return */ @PostMapping("/file-and-bean") public FileBeanBO fileAndJavaBean(@RequestPart @Validated FileBeanBO bean, @RequestPart MultipartFile[] file) { String collect = Arrays.stream(file).map(MultipartFile::getOriginalFilename).collect(Collectors.joining(",")); bean.setFileName(collect); return bean; } }
FileBeanBO.java
@Data public class SimpleBean { @NotBlank private String username; @Valid @NotEmpty private List<ParamBO> params; @Null(message = "The fileName is not support to be used") private String fileName; @Data public class ParamBO { private String username; private Object data; } }
5.2 前端请求
此处需要特别注意,需要手动指定JavaBean的类型 Content-Type
const fileAndJavaBeanFuc = (methodParam: { file: string | Blob }) => { let formData = new FormData() let paramList = [] for (let i = 0; i < 3; i++) { let param = { username: '参数' + i, data: '参数值' + i } paramList.push(param) } let data = { username: '张三', params: paramList } formData.append('bean', new Blob([JSON.stringify(data)], { type: 'application/json' })) formData.append('file', methodParam.file) fileAndJavaBean(formData).then(resp => { console.log(resp) }) }
fileAndJavaBean 为封装的api请求方法,可查看下文的 param.ts
6 前端封装 param.ts
export const fileAndSimpleParam = (params: any) => { return axios.post('/param/file-simple-param', params) } export const fileAndSimpleJavaBean = (params: any) => { return axios.post('/param/file-simple-bean', params) } export const fileAndJsonStringToJavaBean = (params: any) => { return axios.post('/param/file-and-json', params) } export const fileInJavaBean = (params: any) => { return axios.post('/param/file-in-bean', params, { headers: { 'Content-Type': 'multipart/form-data' } }) } export const fileAndJavaBean = (params: any) => { return axios.post('/param/file-and-bean', params) }
7 后记
以上5种方式,都能实现参数与文件同时接受,至于使用哪一种,看具体需求,参数太多的时候,可以优先考虑@RequestPart注解。
到此这篇关于spring boot项目同时传递参数和文件的多种方式的文章就介绍到这了,更多相关spring boot传递参数和文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!