尝试使用 ng-file-upload 在 Spring 中上传许多文件时出现空列表 <MultipartFile>
Empty List<MultipartFile> when trying to upload many files in Spring with ng-file-upload
我有以下用于一次上传多个文件的控制器方法,也受到 this blog post and answers to this question 的启发:
@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user,
@RequestParam("file") List<MultipartFile> files) {
// handle files
}
但是,尽管请求中包含文件,但文件列表始终为空。
如果我将第三个 MultipartRequest
参数添加到方法中:
public void upload(@PathVariable User user,
@RequestParam("file") List<MultipartFile> files,
MultipartRequest request)
我可以看到它正确包含了我上传的文件:
空 List<MultipartFile>
可能是什么原因?
我正在使用 ng-file-upload 提交文件,但我认为这与问题无关。 Spring 4.2.4.
尝试像这样使用 @ModelAttribute
:
@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user,@ModelAttribute("uploadFile") FileUpload uploadFile) throws IllegalStateException, IOException {
List<MultipartFile> files = uploadFile.getFiles();
...
并创建一个 class 比如:
public class FileUpload {
private List<MultipartFile> files;
public List<MultipartFile> getFiles() {
return files;
}
public void setFiles(List<MultipartFile> files) {
this.files= files;
}
}
我认为在你从前端发送数据的方式中,它不能绑定与java.util.List。如果您根据请求创建了一个 JSON 数据,并且您使用 @RequestBody 注释了您的列表,例如:
@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user,
@RequestBody List<MultipartFile> files) {
// handle files
}
这应该有效。一些信息 here.
问题是使用 Upload
服务时的 ng-file-upload by default submits array of files using names file[0]
, file[1]
etc. It is configurable with the arrayKey
值。将其设置为空字符串会强制文件在相同的 file
密钥下发送,该密钥已使用 Spring 正确解析,并且 @RequestParam("file") List<MultipartFile>
包含已提交的所有文件。
Upload.upload({url: url, data: {file: arrayOfFiles}, arrayKey: ''})
这对我有用,将带有多个文件附件的大 'email' 对象从 UI 发送到后端:
Angular
sendEmailWithAttachments(taskId: string, template: string, email: any, modelConfig: any, files: any[]) {
let formData = new FormData();
formData.append('form', new Blob([JSON.stringify(email)], {type: 'application/json'}));
files.forEach(file => {
formData.append('files', file);
});
return this.$http({
method: 'POST',
data: formData,
url: this.baseUrl + '/' + taskId + '/email-with-attachment?template=' + template,
headers: {
'Content-Type': undefined
},
responseType: 'arraybuffer'
});
}
Java Spring
@RequestMapping(value = "{taskId}/email-with-attachment", method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE)
public void sendEmailWithAttachment(
@PathVariable String taskId,
@RequestParam String template,
@RequestParam("form") MultipartFile form,
@RequestParam("files") List<MultipartFile> files) throws IOException {
Map<String, String> parameters = new ObjectMapper().readValue(form.getInputStream(), HashMap.class);
System.out.println("taskId"+ taskId);
System.out.println("template"+ template);
System.out.println("files"+ files);
System.out.println("parameters"+ parameters);
}
对于多个文件。在您的 java 脚本
中执行此操作
//first add files to form data
var formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append("images", files[i]);
}
//post files to backend e.g using angular
$http.post('upload', formData, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.then(function(response){
console.log("UPLOAD COMPLETE::=> ", response);
}, function (error) {
console.log(error);
});
在您的 java
中执行此操作
//your java method signature
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
public Response uploadImage(RequestParam(value = "images") MultipartFile[] images){
}
我有以下用于一次上传多个文件的控制器方法,也受到 this blog post and answers to this question 的启发:
@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user,
@RequestParam("file") List<MultipartFile> files) {
// handle files
}
但是,尽管请求中包含文件,但文件列表始终为空。
如果我将第三个 MultipartRequest
参数添加到方法中:
public void upload(@PathVariable User user,
@RequestParam("file") List<MultipartFile> files,
MultipartRequest request)
我可以看到它正确包含了我上传的文件:
空 List<MultipartFile>
可能是什么原因?
我正在使用 ng-file-upload 提交文件,但我认为这与问题无关。 Spring 4.2.4.
尝试像这样使用 @ModelAttribute
:
@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user,@ModelAttribute("uploadFile") FileUpload uploadFile) throws IllegalStateException, IOException {
List<MultipartFile> files = uploadFile.getFiles();
...
并创建一个 class 比如:
public class FileUpload {
private List<MultipartFile> files;
public List<MultipartFile> getFiles() {
return files;
}
public void setFiles(List<MultipartFile> files) {
this.files= files;
}
}
我认为在你从前端发送数据的方式中,它不能绑定与java.util.List。如果您根据请求创建了一个 JSON 数据,并且您使用 @RequestBody 注释了您的列表,例如:
@RequestMapping(value = "/{user}/attachment", method = RequestMethod.POST)
@PreAuthorize(...)
public void upload(@PathVariable User user,
@RequestBody List<MultipartFile> files) {
// handle files
}
这应该有效。一些信息 here.
问题是使用 Upload
服务时的 ng-file-upload by default submits array of files using names file[0]
, file[1]
etc. It is configurable with the arrayKey
值。将其设置为空字符串会强制文件在相同的 file
密钥下发送,该密钥已使用 Spring 正确解析,并且 @RequestParam("file") List<MultipartFile>
包含已提交的所有文件。
Upload.upload({url: url, data: {file: arrayOfFiles}, arrayKey: ''})
这对我有用,将带有多个文件附件的大 'email' 对象从 UI 发送到后端:
Angular
sendEmailWithAttachments(taskId: string, template: string, email: any, modelConfig: any, files: any[]) {
let formData = new FormData();
formData.append('form', new Blob([JSON.stringify(email)], {type: 'application/json'}));
files.forEach(file => {
formData.append('files', file);
});
return this.$http({
method: 'POST',
data: formData,
url: this.baseUrl + '/' + taskId + '/email-with-attachment?template=' + template,
headers: {
'Content-Type': undefined
},
responseType: 'arraybuffer'
});
}
Java Spring
@RequestMapping(value = "{taskId}/email-with-attachment", method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE)
public void sendEmailWithAttachment(
@PathVariable String taskId,
@RequestParam String template,
@RequestParam("form") MultipartFile form,
@RequestParam("files") List<MultipartFile> files) throws IOException {
Map<String, String> parameters = new ObjectMapper().readValue(form.getInputStream(), HashMap.class);
System.out.println("taskId"+ taskId);
System.out.println("template"+ template);
System.out.println("files"+ files);
System.out.println("parameters"+ parameters);
}
对于多个文件。在您的 java 脚本
中执行此操作//first add files to form data
var formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append("images", files[i]);
}
//post files to backend e.g using angular
$http.post('upload', formData, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.then(function(response){
console.log("UPLOAD COMPLETE::=> ", response);
}, function (error) {
console.log(error);
});
在您的 java
中执行此操作//your java method signature
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
public Response uploadImage(RequestParam(value = "images") MultipartFile[] images){
}