File upload Spring启动文件上传错误请求400
您好,我正在使用Spring Boot和AngularJs编写一个Web应用程序,需要一个简单的文件上传,目前还不能工作 我已经读到,当mvc依赖项存在时,SpringBoot应该自动配置多部分上传本身。 发件人: 作为自动配置SpringMVC的一部分,SpringBoot将创建一个MultipartConfigElement bean,并为文件上传做好准备 发送请求的Javascript函数:File upload Spring启动文件上传错误请求400,file-upload,parameters,spring-boot,http-status-code-400,bad-request,File Upload,Parameters,Spring Boot,Http Status Code 400,Bad Request,您好,我正在使用Spring Boot和AngularJs编写一个Web应用程序,需要一个简单的文件上传,目前还不能工作 我已经读到,当mvc依赖项存在时,SpringBoot应该自动配置多部分上传本身。 发件人: 作为自动配置SpringMVC的一部分,SpringBoot将创建一个MultipartConfigElement bean,并为文件上传做好准备 发送请求的Javascript函数: var postFormData = function (file, url, successCa
var postFormData = function (file, url, successCallback, errorCallback, progressCallback) {
var xhr = new XMLHttpRequest(),
formData = new FormData();
formData.append("file", file);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
successCallback(xhr.status); //File is Uploaded
} else {
errorCallback(xhr.status);
}
}
};
function progress(evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
progressCallback(percentComplete);
} else {
progressCallback(evt.loaded);
}
}
xhr.open("POST", url, true);
//xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.addEventListener("progress", progress, false);
xhr.send(formData);
}
我的主应用程序类中的多部分配置Bean:
@Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize(MAXIMUM_FILE_SIZE);
factory.setMaxRequestSize(MAXIMUM_FILE_SIZE);
return factory.createMultipartConfig();
}
上载控制器:
@Controller
@RequestMapping("/api")
public class FileUploadController {
@Autowired
UserRepository userRepository;
@Autowired
VolumeMetaRepository volumeMetaRepository;
/**
* Handles File upload of volumedata
*
* @param file Must not be null
**/
@RequestMapping(value = "/volumedata/meta/test", consumes= "multipart/form-data", method=RequestMethod.POST)
@ResponseBody
public void handleFileUpload(
@RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
/* try {
InputStream fileStream = file.getInputStream();
OutputStream out = new FileOutputStream(file.getOriginalFilename());
IOUtils.copy(fileStream, out);
} catch (IOException e) {
throw new IllegalStateException("Error uploading file.", e);
}*/
/* String filePath = request.getServletContext().getRealPath("/");
try {
file.transferTo(new File(filePath+ "/" + file.getOriginalFilename()));
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
由于还有其他Stackoverflow线程,因此新的Spring启动版本使用“1.2.2.BUILD-SNAPSHOT”解决了问题,我的gradle依赖项:
version = '1.2.2.BUILD-SNAPSHOT'
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version:version
compile group: 'org.springframework.boot', name: 'spring-boot-starter-aop', version:version
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version:version
compile group: 'org.springframework.hateoas', name: 'spring-hateoas', version:'0.16.0.RELEASE'
compile group: 'org.springframework.data', name: 'spring-data-rest-webmvc', version:'2.1.4.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-security', version:version
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-rest', version:version
compile group: 'commons-io', name: 'commons-io', version:'2.1'
compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version:'2.3.4'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-integration', version:version
compile group: 'org.springframework.boot', name: 'spring-boot-starter-websocket', version:version
compile group: 'org.springframework.session', name: 'spring-session', version:'1.0.0.BUILD-SNAPSHOT'
compile group: 'org.springframework.data', name: 'spring-data-redis', version:'1.4.1.RELEASE'
compile group: 'redis.clients', name: 'jedis', version:'2.4.2'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-remote-shell', version:version
compile group:'com.google.guava', name:'guava', version:'18.0'
compile files ('lib/vendor/niftijio.jar');
compile("com.h2database:h2")
testCompile(group: 'org.springframework.boot', name: 'spring-boot-starter-test', version:'1.1.6.RELEASE') {
exclude(module: 'commons-logging')
}
testCompile group: 'com.jayway.jsonpath', name: 'json-path', version:'0.9.1'
testCompile 'org.springframework:spring-test:3.2.3.RELEASE'
testCompile 'junit:junit:4.+'
testCompile "org.mockito:mockito-all:1.9.5"
}
引发的错误是:
{
"timestamp" : "2015-01-19T10:22:53.710Z",
"status" : 400,
"error" : "Bad Request",
"exception" : "org.springframework.web.bind.MissingServletRequestParameterException",
"message" : "Required MultipartFile parameter 'file' is not present",
"path" : "/api/volumedata/meta/test"
}
它告诉我“file”参数不存在,但我的请求负载显示该参数存在
Request Payload:
------WebKitFormBoundary40qPAhpvA20pd8V1
Content-Disposition: form-data; name="file"
C:\fakepath\test.gz
------WebKitFormBoundary40qPAhpvA20pd8V1--
有人知道我的配置中缺少了什么,或者什么可能导致错误吗
提前感谢我找到了错误的原因。它不是源于我的Spring控制器,而是源于我的angularJS html代码 这是我的上传输入字段:
<div class="form-group"
ng-class="{ 'has-error': volume_upload_form.file_field.$invalid && volume_upload_form.file_field.$dirty}">
<label name=file-field-label>Volume Dataset</label>
<input value=file
name=file
ng-model=upload.file
required
id=file
file_ext_validation
type="file"
extensions="nii,NII,gz,jpeg,JPG"/>
<div class="error"
ng-show="volume_upload_form.volume.$invalid">
<small class="error"
ng-show="volume_upload_form.volume.$error.fileExtValidation">
File must be of type ".nii"
</small>
</div>
</div>
但是Angular默认情况下不支持文件输入html字段。因此,upload.file中只存储了一个包含文件路径的字符串,而不是实际的文件对象。我必须编写一个自定义指令:
var fileModel = function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function () {
scope.$apply(function () {
modelSetter(scope, element[0].files[0]);
});
});
}
};
}
module.exports = fileModel;
返回实际的文件对象。我新上传的html代码如下:
<div class="form-group"
ng-class="{ 'has-error': volume_upload_form.file_field.$invalid && volume_upload_form.file_field.$dirty}">
<label name=file-field-label>Volume Dataset</label>
<input name=file
file-model="upload.fileModel"
ng-model="file"
required
file_ext_validation
type="file"
extensions="nii,NII,gz,jpeg,JPG"/>
<div class="error"
ng-show="volume_upload_form.volume.$invalid">
<small class="error"
ng-show="volume_upload_form.volume.$error.fileExtValidation">
File must be of type ".nii"
</small>
</div>
</div>
将文件对象从文件输入字段链接到角度控制器。
这是正确的请求负载
------WebKitFormBoundaryR1AXAwLepSUKJB3i
Content-Disposition: form-data; name="file"; filename="test.nii.gz"
Content-Type: application/x-gzip
------WebKitFormBoundaryR1AXAwLepSUKJB3i--
我遇到了这个问题,因为我命名的var不正确 在接收文件的控制器中,
RequestParam(“文件”)
需要一个名为“file”的参数
但我把它命名为“bundle”。所以这是一个不好的请求
file-model="upload.fileModel"
------WebKitFormBoundaryR1AXAwLepSUKJB3i
Content-Disposition: form-data; name="file"; filename="test.nii.gz"
Content-Type: application/x-gzip
------WebKitFormBoundaryR1AXAwLepSUKJB3i--