在 Spring Boot REST API 中上传文件
Posted
技术标签:
【中文标题】在 Spring Boot REST API 中上传文件【英文标题】:Upload file in Spring Boot REST API 【发布时间】:2018-10-08 23:54:54 【问题描述】:我正在尝试使用 Spring Boot @RestController
上传文件:
@RequestMapping(value = "/register", method = RequestMethod.POST)
public AppResponse registerUserFromApp(
@RequestBody UserInfo userInfo,
@RequestParam(value = "file", required = false) CommonsMultipartFile file,
@RequestParam(value = "inviteCode", required = false) String inviteCode)
有了这个定义,我尝试了这个 Postman 请求: 这不起作用。
我尝试将此添加到我的RequestMapping
:
@RequestMapping(value = "/register", method = RequestMethod.POST, consumes = "multipart/form-data")
这给了我同样的错误。
对于userInfo
,我按照another SO answer 的建议将值作为JSON 发送到表单数据字段本身。不起作用,同样的错误。
正如其他一些 SO 答案中所建议的那样,我还确保我没有在 Postman 中发送任何标题。
我也尝试在application.properties
中添加以下属性:
spring.http.multipart.enabled=false
同样的错误。我也试过MultipartFile
而不是CommonsMultipartFile
,完全没有区别。
我做错了什么?我也想在请求中将图像作为文件和UserInfo
对象发送。邮递员的例子将不胜感激。
【问题讨论】:
【参考方案1】:我通过在 DTO-Bean 中添加多个部分文件并将邮递员中的每个字段添加为字符串来完成。 spring boot 将匹配文件并分配值,请参见下面的示例
这是我的Account Bean,用于接受邮递员的请求
// done test 100%
@JsonPropertyOrder( "email", "password", "file" )
public class AccountBean
@ApiModelProperty(notes = "Enter Email", name = "email", value = "nabeel.amd93@gmail.com", required = true)
@NotNull(message = "Email contain null")
@NotBlank(message = "Email Contain blank")
@Email(message = "Email wrong type")
private String email;
@ApiModelProperty(notes = "Enter Password", name = "password", value = "ballistic", required = true)
@NotNull(message = "Password contain null")
@NotBlank(message = "Password contain blank")
private String password;
@ApiModelProperty(notes = "Enter file", name = "file", value = "xyz", required = true)
@NotNull(message = "File contain null")
@ValidImage(message = "File support type => \"image/jpeg\", \"image/png\", \"image/jpg\"")
private MultipartFile file;
public AccountBean()
public String getEmail() return email;
public void setEmail(String email) this.email = email;
public String getPassword() return password;
public void setPassword(String password) this.password = password;
public MultipartFile getFile() return file;
public void setFile(MultipartFile file) this.file = file;
@Override
public String toString() return "AccountBean" + "email='" + email + '\'' + ", password='" + password + '\'' + ", repository=" + file + '';
Rest-Api
@ApiOperation(value = "File upload with object field", response = APIResponse.class)
@ApiResponses(value =
@ApiResponse(code = 200, message = "Success", response = String.class),
@ApiResponse(code = 404, message = "Not Found"))
@RequestMapping(value = "/save/account/local", method = RequestMethod.POST)
public ResponseEntity<APIResponse<?>> saveAccountWithSingleFile(
@ApiParam(name = "account", value = "Select File with Dto field", required = true)
@Valid AccountBean accountBean, BindingResult bindingResult) throws IllegalBeanFieldException
long sTime = System.nanoTime();
logger.info("save file with account process");
if(bindingResult.hasErrors())
AtomicInteger bind = new AtomicInteger();
HashMap<String, HashMap<String, Object>> error = new HashMap<>();
bindingResult.getFieldErrors().forEach(fieldError ->
String key = "key-"+bind;
HashMap<String, Object> value = new HashMap<>();
value.put("objectName", fieldError.getObjectName());
value.put("field", fieldError.getField() != null ? fieldError.getField() : "null");
value.put("reject", fieldError.getRejectedValue() != null ? fieldError.getRejectedValue() : "null");
value.put("message", fieldError.getDefaultMessage());
error.put(key, value);
bind.getAndIncrement();
);
throw new IllegalBeanFieldException(error.toString());
this.apiResponse = this.uploadFile(accountBean.getFile()).getBody();
logger.debug("account file save time " + ((System.nanoTime() - sTime) / 1000000) + ".ms");
if(this.apiResponse.getReturnCode().equals(HttpStatus.OK))
// add-info to the account
Account account = new Account();
account.setEmail(accountBean.getEmail());
account.setPassword(accountBean.getPassword());
account.setFileInfo((FileInfo) this.apiResponse.getEntity());
account = this.iAccountService.saveAccount(account);
logger.info("account with file single file info save time :- " + ((System.nanoTime() - sTime) / 1000000) + ".ms");
this.apiResponse = new APIResponse<Account>("File save with account", HttpStatus.OK, account);
logger.info("account added " + this.apiResponse.toString());
logger.info("total response time :- " + ((System.nanoTime() - sTime) / 1000000) + ".ms");
return new ResponseEntity<APIResponse<?>>(this.apiResponse, HttpStatus.OK);
邮递员输入
以https://github.com/NABEEL-AHMED-JAMIL/fserver项目为例
【讨论】:
【参考方案2】:带有自定义对象的多部分表单数据将被接受为字符串。所以你的控制器如下所示。
@RequestMapping(value = "/register", method = RequestMethod.POST)
public AppResponse registerUserFromApp(
@RequestBody String userInfo,
@RequestParam(value = "file", required = false) CommonsMultipartFile file,
@RequestParam(value = "inviteCode", required = false) String inviteCode)
ObjectMapper obj=new ObjectMapper();
UserInfo userInfo=obj.readValue(clientData, UserInfo.class);
您必须使用 ObjectMapper 将 String 转换为 pojo。希望这会有所帮助。
【讨论】:
或者检查这个***.com/questions/21329426/…以上是关于在 Spring Boot REST API 中上传文件的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 2 Rest Api Example
如何在 Spring Boot REST API 上设置超时?
Spring Boot - 模拟对外部 API 的 POST REST 请求
Spring boot 和 Jira REST API 在 maven 中给出依赖错误