[SPRING] Angular2에서 REST API로 파일 업로드
SPRINGAngular2에서 REST API로 파일 업로드
사실, 저는 Angular 2로 코딩 된 인터페이스를 가진 Spring REST API에 대해 작업하고 있습니다.
내 문제는 Angular 2로 파일을 업로드 할 수 없다는 것입니다.
Java의 내 웹 리소스는 다음과 같습니다.
@RequestMapping(method = RequestMethod.POST, value = "/upload")
public String handleFileUpload(@RequestParam MultipartFile file) {
//Dosomething
}
그리고 그것은 Auth 헤더 등으로 URL 요청을 통해 호출 할 때 완벽하게 작동합니다 ... (Chrome 용 고급 휴식 클라이언트 확장 프로그램 사용)
증명 : (모든 경우 잘 작동합니다)
나는
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
Spring 설정 파일과 Pom 의존성
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2</version>
</dependency>
그러나 웹 양식으로 같은 일을하려고 할 때 :
<input type="file" #files (change)="change(files)"/>
<pre>{{fileContents$|async}}</pre>
(변경) 메소드 사용 :
change(file) {
let formData = new FormData();
formData.append("file", file);
console.log(formData);
let headers = new Headers({
'Authorization': 'Bearer ' + this.token,
'Content-Type': 'multipart/form-data'
});
this.http.post(this.url, formData, {headers}).map(res => res.json()).subscribe((data) => console.log(data));
/*
Observable.fromPromise(fetch(this.url,
{method: 'post', body: formData},
{headers: this.headers}
)).subscribe(()=>console.log('done'));
*/
}
내 웹 서비스는 tomcat 로그에 다음과 같은 오류 500을 반환합니다. http://pastebin.com/PGdcFUQb
나는 'Content-Type'을 시도했다 : 정의되지 않은 메소드도 성공했지만 성공하지 못했다. (웹 서비스는 415 에러를 리턴한다.
누군가 문제의 원인을 파악하는 데 도움을 줄 수 있습니까?
문제가 해결되면, 나중에이 코드를 내 코드로 업데이트 할 것이다. :) 그러나, 완벽하게 잘 작동하는 플 런커에 대해 살펴 보자. 감사.
해결법
-
==============================
1.이것은 최종 릴리스에서 실제로 실제로 쉽습니다. 내가 만났던 대부분의 정보가 구식이기 때문에 내 머리를 감싸는 데 시간이 좀 걸렸다. 다른 사람들이이 문제로 어려움을 겪고있는 경우에 대비하여 여기에 내 솔루션을 게시하십시오.
이것은 최종 릴리스에서 실제로 실제로 쉽습니다. 내가 만났던 대부분의 정보가 구식이기 때문에 내 머리를 감싸는 데 시간이 좀 걸렸다. 다른 사람들이이 문제로 어려움을 겪고있는 경우에 대비하여 여기에 내 솔루션을 게시하십시오.
import { Component, ElementRef, Input, ViewChild } from '@angular/core'; import { Http } from '@angular/http'; @Component({ selector: 'file-upload', template: '<input type="file" [multiple]="multiple" #fileInput>' }) export class FileUploadComponent { @Input() multiple: boolean = false; @ViewChild('fileInput') inputEl: ElementRef; constructor(private http: Http) {} upload() { let inputEl: HTMLInputElement = this.inputEl.nativeElement; let fileCount: number = inputEl.files.length; let formData = new FormData(); if (fileCount > 0) { // a file was selected for (let i = 0; i < fileCount; i++) { formData.append('file[]', inputEl.files.item(i)); } this.http .post('http://your.upload.url', formData) // do whatever you do... // subscribe to observable to listen for response } } }
다음과 같이 사용하십시오.
<file-upload #fu (change)="fu.upload()" [multiple]="true"></file-upload>
그게 전부입니다.
또는 이벤트 객체를 캡처하고 srcElement에서 파일을 가져옵니다. 솔직히 말해서 어떤 방법이 다른 것보다 낫다면 확실하지 않습니다!
FormData는 IE10 +이므로, IE9를 지원해야한다면 polyfill이 필요합니다.
업데이트 2017-01-07
여러 파일의 업로드를 처리 할 수 있도록 업데이트 된 코드 또한 내 원래의 대답은 FormData에 관한 중요한 비트를 잃어 버렸습니다. (실제로 업로드 로직을 내 자신의 앱에서 별도의 서비스로 옮겼기 때문에 거기에서 처리하고있었습니다.)
-
==============================
2.사실, 현재 Angular2 HTTP 지원의 게시, 삽입 및 패치 방법에 대해서만 문자열 입력을 제공 할 수 있습니다.
사실, 현재 Angular2 HTTP 지원의 게시, 삽입 및 패치 방법에 대해서만 문자열 입력을 제공 할 수 있습니다.
이를 지원하려면 아래에 설명 된대로 XHR 객체를 직접 활용해야합니다.
import {Injectable} from 'angular2/core'; import {Observable} from 'rxjs/Rx'; @Injectable() export class UploadService { constructor () { this.progress$ = Observable.create(observer => { this.progressObserver = observer }).share(); } private makeFileRequest (url: string, params: string[], files: File[]): Observable { return Observable.create(observer => { let formData: FormData = new FormData(), xhr: XMLHttpRequest = new XMLHttpRequest(); for (let i = 0; i < files.length; i++) { formData.append("uploads[]", files[i], files[i].name); } xhr.onreadystatechange = () => { if (xhr.readyState === 4) { if (xhr.status === 200) { observer.next(JSON.parse(xhr.response)); observer.complete(); } else { observer.error(xhr.response); } } }; xhr.upload.onprogress = (event) => { this.progress = Math.round(event.loaded / event.total * 100); this.progressObserver.next(this.progress); }; xhr.open('POST', url, true); xhr.send(formData); }); } }
자세한 내용은이 plunkr을 참조하십시오 : https://plnkr.co/edit/ozZqbxIorjQW15BrDFrg?p=info.
Angular repo에는 문제와 관련하여 보류중인 PR이 있습니다.
-
==============================
3.이것은 나를 위해 일했다 :
이것은 나를 위해 일했다 :
<input type="file" (change)="onChange($event)" required class="form-control " name="attach_file" id="attach_file"> onChange(event: any) { let fileList: FileList = event.target.files; if(fileList.length > 0) { let file: File = fileList[0]; let formData:FormData = new FormData(); formData.append('degree_attachment', file, file.name); let headers = new Headers(); headers.append('Accept', 'application/json'); let options = new RequestOptions({ headers: headers }); this.http.post('http://url', formData,options) .map(res => res.json()) .catch(error => Observable.throw(error)) .subscribe( data => console.log('success'), error => console.log(error) ) }}
-
==============================
4.이것은 나를 위해 일했습니다 : Angular 2는 파일 업로드에 대한 훌륭한 지원을 제공합니다 :
이것은 나를 위해 일했습니다 : Angular 2는 파일 업로드에 대한 훌륭한 지원을 제공합니다 :
<input type="file" (change)="fileChange($event)" placeholder="Upload file" accept=".pdf,.doc,.docx"> fileChange(event) { let fileList: FileList = event.target.files; if(fileList.length > 0) { let file: File = fileList[0]; let formData:FormData = new FormData(); formData.append('uploadFile', file, file.name); let headers = new Headers(); headers.append('Content-Type', 'multipart/form-data'); headers.append('Accept', 'application/json'); let options = new RequestOptions({ headers: headers }); this.http.post(URL, formData, options) .map(res => res.json()) .catch(error => Observable.throw(error)) .subscribe( data => console.log('success'), error => console.log(error) ) } }
오류가 발생했습니다 : java.io.IOException : RESTEASY007550 : 다중 부분에 대한 경계를 가져올 수 없습니다.
이 문제를 해결하려면 "Content-Type" "multipart / form-data"
-
==============================
5.이 스레드는 매우 도움이되어 내 솔루션을 공유해야한다고 느꼈습니다. 우드로 형제의 대답은 나의 출발점이었습니다. 또한 Rob Gwynn-Jones의 "수동으로 Content-Type 헤더를 설정하지 않도록주의하십시오."라는 메시지에주의를 환기시키고 싶습니다.이 헤더는 매우 중요하며 시간을 많이 절약 해줍니다.
이 스레드는 매우 도움이되어 내 솔루션을 공유해야한다고 느꼈습니다. 우드로 형제의 대답은 나의 출발점이었습니다. 또한 Rob Gwynn-Jones의 "수동으로 Content-Type 헤더를 설정하지 않도록주의하십시오."라는 메시지에주의를 환기시키고 싶습니다.이 헤더는 매우 중요하며 시간을 많이 절약 해줍니다.
동일한 이름을 가진 여러 파일 (다른 폴더의 파일)은 함께 업로드 할 수 있지만 같은 파일은 업로드 목록에 두 번 추가되지 않습니다 (이것은 사소한 것이 아닙니다!).
'@ angular / core'에서 {Component, ElementRef, Input, ViewChild}를 가져 오십시오; 가져 오기 {Http} '@ angular / http'에서; @구성 요소({ 선택자 : '파일 업로드', 템플릿 : '' }) 수출 클래스 FileUploadComponent { @Input () multiple : 부울 = 거짓; @ViewChild ( 'fileInput') inputEl : ElementRef; 파일 : 배열
= []; fileObjects : Array = []; fileKeys : Array = []; fileCount : 숫자 = 0; 생성자 (개인 http : http) {} addFiles (콜백 : any) { const inputEl : HTMLInputElement = this.inputEl.nativeElement; const newCount : number = inputEl.files.length; for (let i = 0; i 'addFiles'의 콜백을 통해 구성 요소 외부에서 업로드가 수행 될 수 있습니다. 구성 요소는 다음과 같이 사용됩니다.
<파일 업로드 #fu (변경) = "fu.addFiles (setFiles.bind (this))"[다중] = "true"> file-
'setFiles'는 콜백입니다. 이 컨텍스트에서 'this'는 상위 구성 요소입니다.
setFiles (files : Array
) {this.files = files; } 남아있는 것은 업로드 API (상위 구성 요소에도 있음)를 호출하기 전에 멀티 파트 페이로드를 첨부하는 것입니다.
const formData = new FormData (); for (let i = 0; i
이것이 도움이되기를 바라며, 필요하다면 고칠 수있어서 기쁘다. 건배!
-
==============================
6.간단한 솔루션을 찾고 코딩을 직접하고 싶지 않은 경우이 라이브러리를 사용하는 것이 좋습니다.
간단한 솔루션을 찾고 코딩을 직접하고 싶지 않은 경우이 라이브러리를 사용하는 것이 좋습니다.
https://www.npmjs.com/package/angular2-http-file-upload
-
==============================
7.
this.uploader.onBeforeUploadItem = function(item) { item.url = URL.replace('?', "?param1=value1"); }
-
==============================
8.
fileUpload() { const formData = new FormData(); const files = this.filesToUpload; for (let i = 0; i < files.length; i++) { formData.append('file', files.item(i)); formData.append('Content-Type', 'application/json'); formData.append('Accept', `application/json`); } this.http.post('http://localhost:8080/UploadFile', formData).subscribe(response => console.log(response)); }
그때:
<form (ngSubmit)="upload()"> <input type="file" id="file" multiple (change)="fileUpload($event.target.files)"> <button type="submit">Upload</button> </form>
from https://stackoverflow.com/questions/36352405/file-upload-with-angular2-to-rest-api by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 봄 RestTemplate 시간 초과 (0) | 2018.12.09 |
---|---|
[SPRING] applicationContext를 여러 파일로 분할 (0) | 2018.12.09 |
[SPRING] Spring Boot - 한 곳에서 모든 요청과 응답을 예외로 기록하는 방법? (0) | 2018.12.09 |
[SPRING] Java EE 6 대 Spring 3 스택 [닫힘] (0) | 2018.12.09 |
[SPRING] web.xml의 applicationContext.xml 파일 대신 Spring @Configuration annotated 클래스를 등록하는 방법은 무엇입니까? (0) | 2018.12.09 |