Spring Boot 文件上传错误请求 400

2024-05-03

你好,我正在使用 Spring Boot 和 AngularJs 编写一个 Web 应用程序,需要一个简单的文件上传,但目前无法正常工作。

我已经读到,当 mvc 依赖项存在时,Spring Boot 应该自动配置分段上传本身。 从 :https://spring.io/guides/gs/uploading-files/ https://spring.io/guides/gs/uploading-files/

作为自动配置 Spring MVC 的一部分,Spring Boot 将创建一个 MultipartConfigElement bean 并为文件上传做好准备。

发送请求的 Javascript 函数:

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 boot 版本解决了我使用“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"
}

它告诉我“文件”参数不存在,但我的请求负载显示该参数存在。

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>

正如您所看到的,也使用默认的 ng-model 与我的角度控制器进行通信(“upload”是我的控制器别名)。

ng-model=upload.file

但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;

它返回实际的 File 对象。我的新上传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>

你可以看到

file-model="upload.fileModel"

将文件对象从文件输入字段链接到角度控制器。 这是正确的请求负载。

------WebKitFormBoundaryR1AXAwLepSUKJB3i
Content-Disposition: form-data; name="file"; filename="test.nii.gz"
Content-Type: application/x-gzip


------WebKitFormBoundaryR1AXAwLepSUKJB3i--
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Boot 文件上传错误请求 400 的相关文章

随机推荐