0


spring boot项目同时传递参数和文件的多种方式

在开发接口中,遇到了需要同时接收参数和文件的情况,可以有多种方式实现文件+参数的接收,这里基于spring boot 3 + vue 3 + axios,做一个简单的代码演示。

1 简单参数 + 文件参数

参数较少时,比较方便,直接参数接受即可

1.1 后端接口

@RestController@RequestMapping("/param")@ValidatedpublicclassFileParamControllerextendsBaseController{/**
     * 简单参数
     *
     * @param test1
     * @param test2
     * @param file
     * @return
     */@PostMapping("/file-simple-param")publicMap<String,Object>fileAndSimpleParam(@RequestParam@NotBlankString test1,@RequestParam@NotBlankString test2,@RequestParamMultipartFile file){Map<String,Object> objectMap =newHashMap<>();
        objectMap.put("test1", test1);
        objectMap.put("test2", test2);
        objectMap.put("fileName", file.getOriginalFilename());return objectMap;}}

1.2 前端请求

constfileAndSimpleParamFuc=(methodParam:{ file:string| Blob })=>{let formData =newFormData()
    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")@ValidatedpublicclassFileParamControllerextendsBaseController{/**
     * 简单参数转JavaBean接收,不支持如:LIst<xxx> 这样的属性
     *
     * @param bean
     * @param file
     * @return
     */@PostMapping("/file-simple-bean")publicSimpleBeanfileAndSimpleJavaBean(@ValidatedSimpleBean bean,@RequestParamMultipartFile file){
        bean.setFileName(file.getOriginalFilename());return bean;}}

SimpleBean.java

@DatapublicclassSimpleBean{@NotBlankprivateString test1;@NotBlankprivateString test2;@Null(message ="The fileName is not support to be used")privateString fileName;}

2.2 前端请求

constfileAndSimpleJavaBeanFuc=(methodParam:{ file:string| Blob })=>{let formData =newFormData()
    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")@ValidatedpublicclassFileParamControllerextendsBaseController{/**
     * 参数转字符串接收,支持复杂参数属性,如:List<xxx>
     *
     * @param bean
     * @param file
     * @return
     */@PostMapping("/file-and-json")publicSimpleBeanfileAndJsonJavaBean(String bean,@RequestParamMultipartFile file){SimpleBean simpleBean = JSON.parseObject(bean,SimpleBean.class);//自定义参数校验List<String> valid =ValidatorUtils.validFast(simpleBean);if(!valid.isEmpty()){thrownewFailException(String.join(",", valid));}
        simpleBean.setFileName(file.getOriginalFilename());return simpleBean;}}

SimpleBean.java

@DatapublicclassSimpleBean{@NotBlankprivateString test1;@NotBlankprivateString test2;privateList<ParamBO> params;@Null(message ="The fileName is not support to be used")privateString fileName;}

ValidatorUtils.java

借助spring的参数校验做自定义调用

publicclassValidatorUtils{privatestaticfinalValidator VALIDATOR_FAST =Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator();privatestaticfinalValidator VALIDATOR_ALL =Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator();privateValidatorUtils(){}/**
     * 参数校验,遇到第一个不合法的字段直接返回不合法字段,后续字段不再校验
     *
     * @param object
     * @return
     * @param <T>
     */publicstatic<T>List<String>validFast(T object,Class<?>... groups){returnvalid(VALIDATOR_FAST, object, groups);}/**
     * 校验所有字段并返回不合法字段
     *
     * @param object
     * @return
     * @param <T>
     */publicstatic<T>List<String>validAll(T object,Class<?>... groups){returnvalid(VALIDATOR_ALL, object, groups);}privatestatic<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 前端请求

constfileAndJsonStringToJavaBeanFuc=(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 =newFormData()
    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")@ValidatedpublicclassFileParamControllerextendsBaseController{/**
     * 文件放入JavaBean一起提交
     *
     * @param bean
     * @return
     */@PostMapping(value ="/file-in-bean")publicStringfileInJavaBean(@ValidatedFileInBeanBO bean){
        bean.setFileName(bean.getFile().getOriginalFilename());return bean.getFile().getOriginalFilename();}}

FileInBeanBO.java

@DatapublicclassSimpleBean{@NotBlankprivateString test1;@NotBlankprivateString test2;@Null(message ="The fileName is not support to be used")privateString fileName;privateMultipartFile file;}

4.2 前端请求

此处需要特别注意,需要修改Content-Type

constfileInJavaBeanFuc=(methodParam:{ file:string| Blob })=>{let formData =newFormData()
    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")@ValidatedpublicclassFileParamControllerextendsBaseController{/**
     * 参数与文件分开接收,支持复杂参数属性,如:List<xxx>
     *
     * @param bean
     * @param file
     * @return
     */@PostMapping("/file-and-bean")publicFileBeanBOfileAndJavaBean(@RequestPart@ValidatedFileBeanBO bean,@RequestPartMultipartFile[] file){String collect =Arrays.stream(file).map(MultipartFile::getOriginalFilename).collect(Collectors.joining(","));
        bean.setFileName(collect);return bean;}}

FileBeanBO.java

@DatapublicclassSimpleBean{@NotBlankprivateString username;@Valid@NotEmptyprivateList<ParamBO> params;@Null(message ="The fileName is not support to be used")privateString fileName;@DatapublicclassParamBO{privateString username;privateObject data;}}

5.2 前端请求

此处需要特别注意,需要手动指定JavaBean的类型 Content-Type

constfileAndJavaBeanFuc=(methodParam:{ file:string| Blob })=>{let formData =newFormData()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',newBlob([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

exportconstfileAndSimpleParam=(params:any)=>{return axios.post('/param/file-simple-param', params)}exportconstfileAndSimpleJavaBean=(params:any)=>{return axios.post('/param/file-simple-bean', params)}exportconstfileAndJsonStringToJavaBean=(params:any)=>{return axios.post('/param/file-and-json', params)}exportconstfileInJavaBean=(params:any)=>{return axios.post('/param/file-in-bean', params,{
        headers:{'Content-Type':'multipart/form-data'}})}exportconstfileAndJavaBean=(params:any)=>{return axios.post('/param/file-and-bean', params)}

7 后记

以上5种方式,都能实现参数与文件同时接受,至于使用哪一种,看具体需求,参数太多的时候,可以优先考虑@RequestPart注解。


本文转载自: https://blog.csdn.net/Vampire_1122/article/details/127686225
版权归原作者 kangaroo. 所有, 如有侵权,请联系我们删除。

“spring boot项目同时传递参数和文件的多种方式”的评论:

还没有评论