1

안녕하세요, Spring Boot 및 AngularJs를 사용하여 웹 응용 프로그램을 작성하고 있으며 지금은 작동하지 않는 간단한 파일 업로드가 필요합니다.봄 부팅 파일 업로드 잘못된 요청 400

이미 mvc 의존성이 존재할 때 스프링 부트 자체가 멀티 파트 업로드 자체를 자동 구성해야한다고 읽었습니다. 에서 : https://spring.io/guides/gs/uploading-files/

자동 구성 스프링 MVC를의 일환으로, 봄 부팅은 MultipartConfigElement 빈을 생성하고 파일 업로드에 대한 자체 준비 할 것입니다.

요청을 전송

자바 스크립트 기능 :

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 
    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 스레드는

{ 
    "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" 
} 

그것은 "파일"하더군요 :

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" 
} 

던진 오류가 있습니다 : 봄 승 버전, '1.2.2.BUILD 스냅 샷'을 사용하여 문제 임 해결 내 Gradle을 종속 부팅 매개 변수가 없지만 내 요청 페이로드에 매개 변수가 있음이 표시됩니다.

Request Payload: 
------WebKitFormBoundary40qPAhpvA20pd8V1 
Content-Disposition: form-data; name="file" 

C:\fakepath\test.gz 
------WebKitFormBoundary40qPAhpvA20pd8V1-- 

누군가 내 구성에 누락 된 아이디어가 있습니까? 아니면 무엇이 오류를 일으킬 수 있습니까?

미리 감사드립니다.

답변

3

오류의 원인을 찾았습니다. 그것은 내 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-모델을 사용하는 것입니다 :

내 업로드 입력 필드했다.

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 객체를 반환합니다. 당신은 각 컨트롤러에 파일 입력 필드에서

file-model="upload.fileModel" 

링크 파일 개체를 볼 수 있습니다

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

다음과 같이 나의 새로운 업로드 html 코드이었다. 올바른 Payload가 여기에 있습니다.

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


------WebKitFormBoundaryR1AXAwLepSUKJB3i--