使用单个请求发送JSON和图像。Angular + Spring Boot。

5

Spring Rest Controller

@PostMapping(
    value = "/post",
    produces = MediaType.APPLICATION_JSON_VALUE,
    consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}
)
public ResponseEntity<User> handleFileUpload(@RequestParam("user") User user, @RequestPart("file") MultipartFile file) {
    // do something with User and file
    return ResponseEntity.ok().build();
}

Angular Service

@Injectable()
export class UploadFileService {

  constructor(private http: HttpClient) { }
  pushFileToStorage(file: File): Observable<HttpEvent<{}>> {
    let formdata: FormData = new FormData();
    formdata.append('file', file);
    formdata.append('user', JSON.stringify(new User('John', 12)))

    const req = new HttpRequest('POST', '/post', formdata, {
      reportProgress: true,
    });

    return this.http.request(req);
  }
}

当我尝试发送请求时,会收到500内部服务器错误

以下是请求头

POST /post HTTP/1.1
Host: localhost:4200
Connection: keep-alive
Content-Length: 152881
Accept: application/json, text/plain, */*
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarydaQb5yaWw2xu1V9r
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

请求有效负载

------WebKitFormBoundarydaQb5yaWw2xu1V9r
Content-Disposition: form-data; name="file"; filename="Screen Shot 2017-10-24 at 8.49.13 PM.png"
Content-Type: image/png


------WebKitFormBoundarydaQb5yaWw2xu1V9r
Content-Disposition: form-data; name="user"

{"name":"John","age":12}
------WebKitFormBoundarydaQb5yaWw2xu1V9r--

注意:如果在Spring rest controller中,将参数类型User更改为String,则可以正常工作。
问题:如何从Angular发送请求,以便在Spring中获取User和MultipartFile,而不是String。

我正在使用Angular 4和Spring Boot 1.5.7。 - A0__oN
你找到这个错误的解决方案了吗?我也遇到了同样的问题,请支持一下。 - Tharaka
1个回答

9

修改

public ResponseEntity<User> handleFileUpload(@RequestParam("user") User user, @RequestPart("file") MultipartFile file)

to

public ResponseEntity<User> handleFileUpload(@RequestPart("user") User user, @RequestPart("file") MultipartFile file)

将请求更改为以下内容将起作用:

curl -i -X POST -H "Content-Type: multipart/form-data" \
-F 'user={"name":"John","age":12};type=application/json' \
-F "file=@myfile.txt" http://localhost:8080/post

对于consumes,只需要MediaType.MULTIPART_FORM_DATA_VALUE

在Angular中发出以上类型的请求,可以这样做:

const userBlob = new Blob(JSON.stringify(new User('John', 12)),{ type: "application/json"});
formdata.append('user', userBlob);

我尝试了相同的操作,但是出现了以下错误:无法转换请求元素:org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: 无法将类型为'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile'的值转换为所需的类型'com.PersonDTO'; 嵌套异常是java.lang.IllegalStateException: 无法将类型为'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile'的值转换为所需的类型'com.PersonDTO':找不到匹配的编辑器或转换策略。 - Tharaka
@dinesh,你能否在一个单独的问题中发布你的代码? - Saheb
1
请参考以下链接:https://stackoverflow.com/questions/50462894/upload-a-json-object-user-information-and-multiple-image-with-single-request - Tharaka
4
我尝试了你的建议,你需要在JSON.stringify(new User('John', 12)中添加[]const myObjStr = JSON.stringify([new User('John', 12)]); const userBlob = new Blob([myObjStr],{ type: "application/json"}); - Ousama
这取决于您希望JSON和后端使用的数据模型。无论是否带有[],都是有效的JSON,如果我们有正确的数据模型来处理它,应该可以正常工作。 - Saheb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接