각도로 파일 업로드?


173

나는 이것이 일반적인 질문이라는 것을 알고 있지만 Angular 2에서 파일을 업로드하지 못했습니다.

1) http://valor-software.com/ng2-file-upload/

2) http://ng2-uploader.com/home

...하지만 실패했습니다. Angular에서 파일을 업로드 한 사람이 있습니까? 어떤 방법을 사용 했습니까? 그렇게하는 방법? 샘플 코드 또는 데모 링크가 제공되면 정말 감사하겠습니다.

답변:


375

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();
        /** In Angular 5, including the header Content-Type can invalidate your request */
        headers.append('Content-Type', 'multipart/form-data');
        headers.append('Accept', 'application/json');
        let options = new RequestOptions({ headers: headers });
        this.http.post(`${this.apiEndPoint}`, formData, options)
            .map(res => res.json())
            .catch(error => Observable.throw(error))
            .subscribe(
                data => console.log('success'),
                error => console.log(error)
            )
    }
}

@ angular / core "사용 :"~ 2.0.0 "및 @ angular / http :"~ 2.0.0 "


5
적어도 내 경우에는 작동하지 않습니다. sailsJs 서버는 빈 파일 배열 / 객체를
받음

20
그것은 나를 위해 일했습니다-나는이 줄에서 일해야했습니다 headers.append('enctype', 'multipart/form-data');( 'Content-Type'을 대체하기 위해 'enctype'을 사용했습니다). 서버 측 코드에 따라 다를 수 있습니다. (ie api)
Ariful Islam

29
Angular 팀이 주제에 대한 문서를 작성한다면 좋을 것입니다. 문서에서 한 줄을 찾을 수 없습니다. 이 코드 샘플이 오래되어 v4 +에서 작동하지 않습니다.
Rob B

10
일부 애플리케이션 서버의 경우 컨텐츠 유형 설정이 거부됩니다. 비워 두어야합니다. let headers = new Headers (); 브라우저가 자동으로 정렬합니다.
PeterS

6
LMFAO는 헤더를 전혀 설정할 필요가 없다는 것을 깨달을 때 까지이 쓰레기로 20 분 동안 고생했습니다. .Net webapi와 함께 angular 4.xx를 사용하는 다른 사람들에게 헤더를 설정하지 마십시오! 그 아웃 @PeterS를 가리키는위한 들으
Jota.Toledo

76

위의 답변에서 Angular 5.x로 이것을 만듭니다.

전화 uploadFile(url, file).subscribe()를 걸어 업로드를 시작하세요

import { Injectable } from '@angular/core';
import {HttpClient, HttpParams, HttpRequest, HttpEvent} from '@angular/common/http';
import {Observable} from "rxjs";

@Injectable()
export class UploadService {

  constructor(private http: HttpClient) { }

  // file from event.target.files[0]
  uploadFile(url: string, file: File): Observable<HttpEvent<any>> {

    let formData = new FormData();
    formData.append('upload', file);

    let params = new HttpParams();

    const options = {
      params: params,
      reportProgress: true,
    };

    const req = new HttpRequest('POST', url, formData, options);
    return this.http.request(req);
  }
}

컴포넌트에서 이와 같이 사용하십시오

  // At the drag drop area
  // (drop)="onDropFile($event)"
  onDropFile(event: DragEvent) {
    event.preventDefault();
    this.uploadFile(event.dataTransfer.files);
  }

  // At the drag drop area
  // (dragover)="onDragOverFile($event)"
  onDragOverFile(event) {
    event.stopPropagation();
    event.preventDefault();
  }

  // At the file input element
  // (change)="selectFile($event)"
  selectFile(event) {
    this.uploadFile(event.target.files);
  }

  uploadFile(files: FileList) {
    if (files.length == 0) {
      console.log("No file selected!");
      return

    }
    let file: File = files[0];

    this.upload.uploadFile(this.appCfg.baseUrl + "/api/flash/upload", file)
      .subscribe(
        event => {
          if (event.type == HttpEventType.UploadProgress) {
            const percentDone = Math.round(100 * event.loaded / event.total);
            console.log(`File is ${percentDone}% loaded.`);
          } else if (event instanceof HttpResponse) {
            console.log('File is completely loaded!');
          }
        },
        (err) => {
          console.log("Upload Error:", err);
        }, () => {
          console.log("Upload done");
        }
      )
  }

6
Angular6와 잘 작동합니다. 감사합니다. 가져 오려면이 라이브러리가 필요합니다. '@ angular / common / http'에서 {HttpClient, HttpParams, HttpRequest, HttpEvent, HttpEventType, HttpResponse} 가져 오기;
Bharathiraja

1
내 경우에는 권한 부여 베어러를 사용하고이 추가 코드를 추가했습니다let params = new HttpParams(); let headers = new HttpHeaders({ 'Authorization': 'Bearer ' + localStorage.getItem('accessToken'), }); const options = { headers: headers, params: params, reportProgress: true, };
Ciprian Dragoe

그것의 가치에 대한 수입 있음을 지적 Observable하고이 HttpEvent에 대한 함수의 반환 형식을 제공하는 형식 유추를 사용하여 전적으로 만약 당신이있는 거 괜찮 생략 할 수있다 uploadFile()! this.http.request()는 이미의 유형을 반환 Observable<HttpEvent<{}>>하므로 요청 호출에 일반 유형을 제공하면 (즉 this.http.request<any>(), 전체 함수가 올바른 유형으로 만 작동 함)
wosevision

2
html 부분은 다음과 같습니다 input type="file" (change)="addFiles($event)" style="display: none" #file multiple> <button mat-raised-button color="primary" (click)="selectFile($event)">Upload File </button>
Shantam Mittal

22

@Eswar에게 감사합니다. 이 코드는 완벽하게 작동했습니다. 솔루션에 특정 사항을 추가하고 싶습니다.

오류가 발생했습니다. java.io.IOException: RESTEASY007550: Unable to get boundary for multipart

이 오류를 해결하려면 "Content-Type" "multipart / form-data"를 제거해야합니다. 내 문제를 해결했습니다.


5
+1. Content-Type을 제거하면 올바르게 생성됩니다. 예 : multipart/form-data; boundary=---------------------------186035562730765173675680113. stackoverflow.com/a/29697774/1475331github.com/angular/angular/issues/11819 도 참조하십시오 .
turdus-merula

1
나는 당신 java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found"과 비슷한 이 오류 를 겪고 있지만 Content-Type헤더를 제거하면 대신 백엔드에서 404를 얻습니다. 우리는 Spring과 Angular 2를 사용하고 있습니다.
Helen

이것은 그의 대답에 대한 주석이어야합니다. 그렇지 않습니까?
MMalke

19

코드 샘플이 약간 구식이기 때문에 Angular 4.3과 새로운 HttpClient API 인 @ angular / common / http를 사용하여 최신 접근 방식을 공유한다고 생각했습니다.

export class FileUpload {

@ViewChild('selectedFile') selectedFileEl;

uploadFile() {
let params = new HttpParams();

let formData = new FormData();
formData.append('upload', this.selectedFileEl.nativeElement.files[0])

const options = {
    headers: new HttpHeaders().set('Authorization', this.loopBackAuth.accessTokenId),
    params: params,
    reportProgress: true,
    withCredentials: true,
}

this.http.post('http://localhost:3000/api/FileUploads/fileupload', formData, options)
.subscribe(
    data => {
        console.log("Subscribe data", data);
    },
    (err: HttpErrorResponse) => {
        console.log(err.message, JSON.parse(err.error).error.message);
    }
)
.add(() => this.uploadBtn.nativeElement.disabled = false);//teardown
}

1
이것에 대한 HTML이 있습니까? 나는 이것이 HttpParams를 사용하고 있다는 것을 좋아한다. 어딘가에 완전한 작업 예제가 있는지 궁금합니다. 감사합니다
Maddy

이 방법으로 여러 파일을 배열로 함께 업로드하는 방법은 무엇입니까? 양식 데이터 객체에 어떻게 추가해야합니까?
SSR


15

Angular 2+에서는 Content-Type을 비워 두는 것이 매우 중요 합니다 . 'Content-Type'을 'multipart / form-data'로 설정하면 업로드가 작동하지 않습니다!

upload.component.html

<input type="file" (change)="fileChange($event)" name="file" />

upload.component.ts

export class UploadComponent implements OnInit {
    constructor(public http: Http) {}

    fileChange(event): void {
        const fileList: FileList = event.target.files;
        if (fileList.length > 0) {
            const file = fileList[0];

            const formData = new FormData();
            formData.append('file', file, file.name);

            const headers = new Headers();
            // It is very important to leave the Content-Type empty
            // do not use headers.append('Content-Type', 'multipart/form-data');
            headers.append('Authorization', 'Bearer ' + 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9....');
            const options = new RequestOptions({headers: headers});

            this.http.post('https://api.mysite.com/uploadfile', formData, options)
                 .map(res => res.json())
                 .catch(error => Observable.throw(error))
                 .subscribe(
                     data => console.log('success'),
                     error => console.log(error)
                 );
        }
    }
}


7

이 간단한 솔루션은 나를 위해 일했습니다 : file-upload.component.html

<div>
  <input type="file" #fileInput placeholder="Upload file..." />
  <button type="button" (click)="upload()">Upload</button>
</div>

그런 다음 XMLHttpRequest 를 사용하여 컴포넌트에서 직접 업로드하십시오 .

import { Component, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: 'app-file-upload',
  templateUrl: './file-upload.component.html',
  styleUrls: ['./file-upload.component.css']
})
export class FileUploadComponent implements OnInit {

  @ViewChild('fileInput') fileInput;

  constructor() { }

  ngOnInit() {
  }

  private upload() {
    const fileBrowser = this.fileInput.nativeElement;
    if (fileBrowser.files && fileBrowser.files[0]) {
      const formData = new FormData();
      formData.append('files', fileBrowser.files[0]);
      const xhr = new XMLHttpRequest();
      xhr.open('POST', '/api/Data/UploadFiles', true);
      xhr.onload = function () {
        if (this['status'] === 200) {
            const responseText = this['responseText'];
            const files = JSON.parse(responseText);
            //todo: emit event
        } else {
          //todo: error handling
        }
      };
      xhr.send(formData);
    }
  }

}

닷넷 코어를 사용하는 경우 매개 변수 이름은 From 필드 이름과 일치해야합니다. 이 경우 파일 :

[HttpPost("[action]")]
public async Task<IList<FileDto>> UploadFiles(List<IFormFile> files)
{
  return await _binaryService.UploadFilesAsync(files);
}

이 답변은 http://blog.teamtreehouse.com/uploading-files-ajax 의 소풍입니다

편집 : 업로드 후 사용자가 새 파일을 선택할 수 있도록 파일 업로드를 지워야합니다. XMLHttpRequest를 사용하는 대신 fetch를 사용하는 것이 좋습니다.

private addFileInput() {
    const fileInputParentNative = this.fileInputParent.nativeElement;
    const oldFileInput = fileInputParentNative.querySelector('input');
    const newFileInput = document.createElement('input');
    newFileInput.type = 'file';
    newFileInput.multiple = true;
    newFileInput.name = 'fileInput';
    const uploadfiles = this.uploadFiles.bind(this);
    newFileInput.onchange = uploadfiles;
    oldFileInput.parentNode.replaceChild(newFileInput, oldFileInput);
  }

  private uploadFiles() {
    this.onUploadStarted.emit();
    const fileInputParentNative = this.fileInputParent.nativeElement;
    const fileInput = fileInputParentNative.querySelector('input');
    if (fileInput.files && fileInput.files.length > 0) {
      const formData = new FormData();
      for (let i = 0; i < fileInput.files.length; i++) {
        formData.append('files', fileInput.files[i]);
      }

      const onUploaded = this.onUploaded;
      const onError = this.onError;
      const addFileInput = this.addFileInput.bind(this);
      fetch('/api/Data/UploadFiles', {
        credentials: 'include',
        method: 'POST',
        body: formData,
      }).then((response: any) => {
        if (response.status !== 200) {
          const error = `An error occured. Status: ${response.status}`;
          throw new Error(error);
        }
        return response.json();
      }).then(files => {
        onUploaded.emit(files);
        addFileInput();
      }).catch((error) => {
        onError.emit(error);
      });
    }

https://github.com/yonexbat/cran/blob/master/cranangularclient/src/app/file-upload/file-upload.component.ts


3

ng2-file-upload 및 ng2-file-upload없이 파일을 업로드하는 방법에 대한 유용한 자습서 입니다.

나를 위해 그것은 많은 도움이됩니다.

현재 튜토리얼에는 몇 가지 실수가 있습니다.

1- 클라이언트는 서버와 동일한 업로드 URL을 가져야 app.component.ts합니다.

const URL = 'http://localhost:8000/api/upload';

const URL = 'http://localhost:3000';

2-서버가 응답을 'text / html'로 전송하므로 app.component.ts변경

.post(URL, formData).map((res:Response) => res.json()).subscribe(
  //map the success function and alert the response
  (success) => {
    alert(success._body);
  },
  (error) => alert(error))

.post(URL, formData)  
.subscribe((success) => alert('success'), (error) => alert(error));

3

양식 필드가있는 이미지를 업로드하려면

SaveFileWithData(article: ArticleModel,picture:File): Observable<ArticleModel> 
{

    let headers = new Headers();
    // headers.append('Content-Type', 'multipart/form-data');
    // headers.append('Accept', 'application/json');

let requestoptions = new RequestOptions({
  method: RequestMethod.Post,
  headers:headers
    });



let formData: FormData = new FormData();
if (picture != null || picture != undefined) {
  formData.append('files', picture, picture.name);
}
 formData.append("article",JSON.stringify(article));

return this.http.post("url",formData,requestoptions)
  .map((response: Response) => response.json() as ArticleModel);
} 

제 경우에는 C #에서 .NET Web Api가 필요했습니다.

// POST: api/Articles
[ResponseType(typeof(Article))]
public async Task<IHttpActionResult> PostArticle()
{
    Article article = null;
    try
    {

        HttpPostedFile postedFile = null;
        var httpRequest = HttpContext.Current.Request;

        if (httpRequest.Files.Count == 1)
        {
            postedFile = httpRequest.Files[0];
            var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
            postedFile.SaveAs(filePath);
        }
        var json = httpRequest.Form["article"];
         article = JsonConvert.DeserializeObject <Article>(json);

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        article.CreatedDate = DateTime.Now;
        article.CreatedBy = "Abbas";

        db.articles.Add(article);
        await db.SaveChangesAsync();
    }
    catch (Exception ex)
    {
        int a = 0;
    }
    return CreatedAtRoute("DefaultApi", new { id = article.Id }, article);
}

3

오늘은 ng2-file-upload 패키지를 angular 6 응용 프로그램 에 통합 했습니다. 매우 간단했습니다. 아래 고급 코드를 찾으십시오.

ng2- 파일 업로드 모듈 가져 오기

app.module.ts

    import { FileUploadModule } from 'ng2-file-upload';

    ------
    ------
    imports:      [ FileUploadModule ],
    ------
    ------

구성 요소 ts 파일 가져 오기 FileUploader

app.component.ts

    import { FileUploader, FileLikeObject } from 'ng2-file-upload';
    ------
    ------
    const URL = 'http://localhost:3000/fileupload/';
    ------
    ------

     public uploader: FileUploader = new FileUploader({
        url: URL,
        disableMultipart : false,
        autoUpload: true,
        method: 'post',
        itemAlias: 'attachment'

        });

      public onFileSelected(event: EventEmitter<File[]>) {
        const file: File = event[0];
        console.log(file);

      }
    ------
    ------

컴포넌트 HTML 추가 파일 태그

app.component.html

 <input type="file" #fileInput ng2FileSelect [uploader]="uploader" (onFileSelected)="onFileSelected($event)" />

온라인 작업 stackblitz 링크 : https://ng2-file-upload-example.stackblitz.io

Stackblitz 코드 예 : https://stackblitz.com/edit/ng2-file-upload-example

공식 문서 링크 https://valor-software.com/ng2-file-upload/


1

options매개 변수를 설정하지 마십시오

this.http.post(${this.apiEndPoint}, formData)

globalHeadersHTTP 팩토리에 설정하지 않았는지 확인하십시오 .


1

가장 간단한 형태로 다음 코드는 Angular 6/7에서 작동합니다.

this.http.post("http://destinationurl.com/endpoint", fileFormData)
  .subscribe(response => {
    //handle response
  }, err => {
    //handle error
  });

다음은 완전한 구현입니다


1

jspdf와 Angular 8

pdf를 생성하고 POST 요청으로 pdf를 업로드하고 싶습니다.

import * as jsPDF from 'jspdf';
import { HttpClient } from '@angular/common/http';

constructor(private http: HttpClient)

upload() {
    const pdf = new jsPDF()
    const blob = pdf.output('blob')
    const formData = new FormData()
    formData.append('file', blob)
    this.http.post('http://your-hostname/api/upload', formData).subscribe()
}

0

참조를 사용하여 파일을 업로드했습니다. 이 방법으로 파일을 업로드하는 데 패키지가 필요하지 않습니다.

// .ts 파일로 작성 될 코드

@ViewChild("fileInput") fileInput;

addFile(): void {
let fi = this.fileInput.nativeElement;
if (fi.files && fi.files[0]) {
  let fileToUpload = fi.files[0];
    this.admin.addQuestionApi(fileToUpload)
      .subscribe(
        success => {
          this.loading = false;
          this.flashMessagesService.show('Uploaded successfully', {
            classes: ['alert', 'alert-success'],
            timeout: 1000,
          });
        },
        error => {
          this.loading = false;
          if(error.statusCode==401) this.router.navigate(['']);
          else
            this.flashMessagesService.show(error.message, {
              classes: ['alert', 'alert-danger'],
              timeout: 1000,
            });
        });
  }

}

// service.ts 파일에 작성 될 코드

addQuestionApi(fileToUpload: any){
var headers = this.getHeadersForMultipart();
let input = new FormData();
input.append("file", fileToUpload);

return this.http.post(this.baseUrl+'addQuestions', input, {headers:headers})
      .map(response => response.json())
      .catch(this.errorHandler);

}

// HTML로 작성 될 코드

<input type="file" #fileInput>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.