REST API에 Angular2를 사용한 파일 업로드
사실, 저는 Angular 2에서 코드화된 인터페이스를 가진 Spring REST API를 작업하고 있습니다.
저의 문제는 Angular 2로 파일을 업로드할 수 없다는 것입니다.
Java의 웹 리소스는 다음과 같습니다.
@RequestMapping(method = RequestMethod.POST, value = "/upload")
public String handleFileUpload(@RequestParam MultipartFile file) {
//Dosomething
}
그리고 Auth 헤더 등으로 URL 요청을 통해 호출하면 완벽하게 작동합니다.(Chrome용 Advanced Rest Client 확장 포함)
증명: (그런 경우에는 모든 것이 정상적으로 작동합니다.
<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'));
*/
}
웹 서비스에서 오류 500을 반환하고 Tomcat 로그: http://pastebin.com/PGdcFUQb
해봤습니다.'Content-Type': undefined
방법도 그렇지만 성공하지 못했습니다. (웹 서비스는 그런 경우 415 오류를 반환합니다.)
누가 뭐가 문제인지 알아내는 것을 도와줄 수 있나요?
문제가 해결되었습니다. 나중에 제 코드로 질문을 업데이트하겠습니다. :) 하지만 플랭크가 완벽하게 잘 작동하는지 확인해 보십시오.감사해요.
이것은 실제로 최종 릴리스에서 매우 쉽게 수행할 수 있습니다.제가 머리를 싸매는 데 시간이 좀 걸렸습니다. 왜냐하면 제가 발견한 대부분의 정보는 구식이기 때문입니다.다른 사람이 이 문제로 어려움을 겪을 경우를 대비하여 제 해결책을 여기에 게시합니다.
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를 지원해야 하는 경우 폴리필이 필요합니다.
2017-01-07 업데이트
여러 파일의 업로드를 처리할 수 있도록 코드가 업데이트되었습니다.또한 저의 원래 답변은 FormData와 관련된 다소 중요한 부분을 누락했습니다(실제 업로드 로직을 제 앱에서 별도의 서비스로 이동했기 때문에 그곳에서 처리했습니다).
사실 현재는 다음에 대한 문자열 입력만 제공할 수 있습니다.post
,put
그리고.patch
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);
});
}
}
자세한 내용은 다음 플런크를 참조하십시오. https://plnkr.co/edit/ozZqbxIorjQW15BrDFrg?p=info
Angular repo에 이와 관련된 문제와 보류 중인 PR이 있습니다.
이것은 나에게 효과가 있었습니다.
<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)
)
}}
이것은 나에게 효과가 있었습니다: 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: Unable to get boundary for multipart
이 문제를 해결하려면 "콘텐츠 유형" "다중 부품/양식 데이터"를 제거해야 합니다.
이 스레드가 너무 도움이 되어 제 솔루션을 공유해야 한다는 생각이 들었습니다.우드로 형의 대답이 제 출발점이었습니다.저는 또한 Rob Gwynn-Jones의 "콘텐츠 유형 헤더를 수동으로 설정하지 않도록 하십시오."라는 매우 중요하고 시간을 절약해 주었습니다.
이 버전에서는 한 번에 모든 파일을 업로드하기 전에 여러 개의 추가/제거 작업(다른 폴더에서)을 수행할 수 있습니다.
이름이 같은 여러 파일(다른 폴더에서)을 함께 업로드할 수 있지만 동일한 파일이 업로드 목록에 두 번 추가되지는 않습니다(보기처럼 사소한 것은 아닙니다!).
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;
files: Array<any> = [];
fileObjects: Array<any> = [];
fileKeys: Array<string> = [];
fileCount: number = 0;
constructor(private http: Http) {}
addFiles(callback: any) {
const inputEl: HTMLInputElement = this.inputEl.nativeElement;
const newCount: number = inputEl.files.length;
for (let i = 0; i < newCount; i ++) {
const obj = {
name: inputEl.files[ i ].name,
type: inputEl.files[ i ].type,
size: inputEl.files[ i ].size,
ts: inputEl.files[ i ].lastModifiedDate
};
const key = JSON.stringify(obj);
if ( ! this.fileKeys.includes(key)) {
this.files.push(inputEl.files.item(i));
this.fileObjects.push(obj);
this.fileKeys.push(key);
this.fileCount ++;
}
}
callback(this.files);
}
removeFile(obj: any) {
const key: string = JSON.stringify(obj);
for (let i = 0; i < this.fileCount; i ++) {
if (this.fileKeys[ i ] === key) {
this.files.splice(i, 1);
this.fileObjects.splice(i, 1);
this.fileKeys.splice(i, 1);
this.fileCount --;
return;
}
}
}
}
'addFiles'의 콜백을 통해 구성 요소 외부에서 업로드할 수 있습니다.구성 요소는 다음과 같이 사용됩니다.
<file-upload #fu (change)="fu.addFiles(setFiles.bind(this))" [multiple]="true"></file-upload>
'setFiles'가 콜백입니다.이 컨텍스트에서 'this'는 상위 구성 요소입니다.
setFiles(files: Array<any>) { this.files = files; }
이제 업로드 API(상위 구성 요소)를 호출하기 전에 멀티파트 페이로드를 연결하면 됩니다.
const formData = new FormData();
for (let i = 0; i < this.files.length; i ++) {
formData.append('file[]', this.files[ i ]);
}
도움이 되기를 바라며, 필요한 경우 수정/업데이트할 수 있습니다.건배!
this.uploader.onBeforeUploadItem = function(item) {
item.url = URL.replace('?', "?param1=value1");
}
간단한 솔루션을 찾고 있지만 직접 코딩을 하고 싶지 않다면 이 라이브러리를 사용하는 것이 좋습니다.
https://www.npmjs.com/package/angular2-http-file-upload
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>
방금 헤더에서 content-type을 제거했습니다.예를 들어, 이것은 우리의 헤더입니다.
let headers = new Headers({
'Authorization': 'Bearer ' + this.token,
'Content-Type': 'multipart/form-data'
});
할 ▁remove다▁what를 제거하는 것입니다.Content-Type
이로부터예:
let headers = new Headers({
'Authorization': 'Bearer ' + this.token,
});
언급URL : https://stackoverflow.com/questions/36352405/file-upload-with-angular2-to-rest-api
'sourcecode' 카테고리의 다른 글
표 행에 여백을 추가하는 방법 (0) | 2023.08.27 |
---|---|
Uncaught TypeError: 정의되지 않은 속성 'msie'를 읽을 수 없습니다. (0) | 2023.08.27 |
Spring ThreadPool 작업에서 corePoolSize와 maxPoolSize의 차이점은 무엇입니까?실행자 (0) | 2023.08.27 |
함수 서명에서 변수 이름 앞의 *와 **는 무엇을 의미합니까? (0) | 2023.08.27 |
셀레늄을 통해 헤드리스 모드에서 크롬 브라우저를 시작하도록 크롬 드라이버를 구성하는 방법은 무엇입니까? (0) | 2023.08.27 |