Unggah File Di Sudut?


173

Saya tahu ini adalah pertanyaan umum tetapi saya gagal mengunggah file dalam Angular 2. Saya sudah mencoba

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

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

... tetapi gagal. Adakah yang mengunggah file di Angular? Metode apa yang Anda gunakan? Bagaimana cara melakukannya? Jika ada kode sampel atau tautan demo yang disediakan, itu akan sangat dihargai.

Jawaban:


375

Angular 2 memberikan dukungan yang baik untuk mengunggah file. Tidak diperlukan perpustakaan pihak ketiga.

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

menggunakan @ angular / core ":" ~ 2.0.0 "dan @ angular / http:" ~ 2.0.0 "


5
itu tidak berfungsi, setidaknya dalam kasus saya. sailsJs server menerima file array / objek kosong
Kaleem Ullah

20
Itu bekerja untuk saya kecuali - saya harus bekerja pada baris ini- headers.append('enctype', 'multipart/form-data');(menggunakan 'enctype' untuk mengganti 'Content-Type'). Mungkin itu tergantung pada kode sisi server. (Yaitu api)
Ariful Islam

29
Menjadi hebat jika tim Angular akan menulis beberapa dokumentasi tentang masalah ini, saya tidak dapat menemukan satu baris tentang hal itu di dokumen mereka. Sampel kode ini kedaluwarsa dan tidak berfungsi dengan v4 +.
Rob B

10
Catatan untuk beberapa server aplikasi, pengaturan tipe konten akan ditolak. Anda harus membiarkannya kosong: biarkan header = Header baru (); Browser akan menyelesaikan semuanya untuk Anda.
PeterS

6
LMFAO berjuang 20 menit dengan omong kosong ini sampai saya menyadari bahwa saya tidak perlu mengatur header sama sekali. Catatan untuk orang lain menggunakan 4.xx sudut dengan. Net webapi, jangan mencoba untuk mengatur header! Terima kasih untuk menunjukkan itu @PeterS
Jota.Toledo

76

Dari jawaban di atas saya membangun ini dengan Angular 5.x

Panggil saja uploadFile(url, file).subscribe()untuk memicu unggahan

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);
  }
}

Gunakan seperti ini di komponen Anda

  // 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
Bekerja dengan baik dengan Angular6. Terima kasih. Dan Anda perlu perpustakaan ini untuk mengimpor. import {HttpClient, HttpParams, HttpRequest, HttpEvent, HttpEventType, HttpResponse} dari '@ angular / common / http';
Bharathiraja

1
dalam kasus saya, saya menggunakan pembawa otorisasi dan menambahkan kode tambahan inilet params = new HttpParams(); let headers = new HttpHeaders({ 'Authorization': 'Bearer ' + localStorage.getItem('accessToken'), }); const options = { headers: headers, params: params, reportProgress: true, };
Ciprian Dragoe

Perlu dicatat bahwa impor untuk Observabledan HttpEventdapat dihilangkan seluruhnya jika Anda setuju dengan menggunakan inferensi tipe untuk menyediakan tipe pengembalian fungsi uploadFile()! this.http.request()sudah mengembalikan jenis Observable<HttpEvent<{}>>, jadi jika Anda memberikan permintaan memanggil jenis umum (yaitu this.http.request<any>()maka seluruh fungsi hanya bekerja dengan jenis yang tepat.
wosevision

2
Bagian html seperti ini 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

Terima kasih kepada @Eswar. Kode ini berfungsi dengan baik untuk saya. Saya ingin menambahkan hal-hal tertentu ke solusinya:

Saya mendapatkan kesalahan: java.io.IOException: RESTEASY007550: Unable to get boundary for multipart

Untuk mengatasi kesalahan ini, Anda harus menghapus "Tipe-Jenis" "multipart / formulir-data". Itu memecahkan masalah saya.


5
+1. Jika Anda menghapus Content-Type, itu akan dihasilkan dengan benar. Misalnya: multipart/form-data; boundary=---------------------------186035562730765173675680113. Lihat juga stackoverflow.com/a/29697774/1475331 dan github.com/angular/angular/issues/11819 .
turdus-merula

1
Saya mendapatkan kesalahan ini java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found"yang mirip dengan kesalahan Anda, namun ketika saya menghapus Content-Typeheader saya mendapatkan 404 dari backend. Kami menggunakan Spring dan Angular 2. Bantuan apa pun dihargai.
Helen

Ini seharusnya hanya komentar atas jawabannya, bukan?
MMalke

19

Karena contoh kode agak ketinggalan jaman saya pikir saya akan membagikan pendekatan yang lebih baru, menggunakan Angular 4.3 dan API HttpClient (er) baru, @ 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
apakah Anda memiliki html untuk ini? Saya suka ini menggunakan HttpParams. Hanya ingin tahu apakah Anda memiliki contoh kerja yang lengkap di suatu tempat. Terima kasih
Maddy

Dengan cara ini, bagaimana saya bisa mengunggah banyak file bersama sebagai sebuah array? bagaimana seharusnya ditambahkan ke objek data formulir?
SSR


15

Dalam Angular 2+, sangat penting untuk membiarkan Konten-Jenis kosong. Jika Anda mengatur 'Jenis-Konten' ke 'multipart / formulir-data', unggahan tidak akan berfungsi!

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

Solusi sederhana ini berhasil untuk saya: file-upload.component.html

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

Dan kemudian lakukan pengunggahan dalam komponen secara langsung dengan 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);
    }
  }

}

Jika Anda menggunakan inti dotnet, nama parameter harus cocok dengan nama bidang dari. file dalam hal ini:

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

Jawaban ini adalah penjiplakan dari http://blog.teamtreehouse.com/uploading-files-ajax

Sunting : Setelah mengunggah, Anda harus menghapus unggahan file sehingga pengguna dapat memilih file baru. Dan daripada menggunakan XMLHttpRequest, mungkin lebih baik menggunakan 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

Ini adalah tutorial yang berguna , cara mengunggah file menggunakan ng2-file-upload dan TANPA ng2-file-upload.

Bagi saya itu sangat membantu.

Saat ini, tutorial berisi beberapa kesalahan:

1- Klien harus memiliki url unggahan yang sama dengan server, jadi di app.component.tsbaris ubah

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

untuk

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

2- Server mengirim respons sebagai 'teks / html', jadi dalam app.component.tsperubahan

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

untuk

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

3

Untuk mengunggah gambar dengan bidang formulir

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);
} 

Dalam kasus saya, saya membutuhkan .NET Web Api di C #

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

Hari ini saya terintegrasi ng2-file-upload ke aplikasi angular 6 saya, itu cukup sederhana, Silakan temukan kode tingkat tinggi di bawah ini.

impor modul unggah file ng2

app.module.ts

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

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

File komponen impor 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 komponen menambahkan tag file

app.component.html

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

Tautan stackblitz Online yang Bekerja: https://ng2-file-upload-example.stackblitz.io

Contoh Kode Stackblitz: https://stackblitz.com/edit/ng2-file-upload-example

Tautan dokumentasi resmi https://valor-software.com/ng2-file-upload/


1

Cobalah untuk tidak mengatur optionsparameter

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

dan pastikan Anda tidak mengatur globalHeadersdi pabrik Http Anda.


1

Dalam bentuk paling sederhana, kode berikut ini berfungsi di Angular 6/7

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

Inilah implementasi lengkapnya


1

jspdf dan Angular 8

Saya menghasilkan pdf dan ingin mengunggah pdf dengan permintaan POST, inilah yang saya lakukan (Untuk lebih jelasnya, saya menghapus beberapa kode dan lapisan layanan)

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

Saya sudah mengunggah file menggunakan referensi. Tidak diperlukan paket untuk mengunggah file dengan cara ini.

// kode yang akan ditulis dalam file .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,
            });
        });
  }

}

// kode yang akan ditulis dalam file 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);

}

// kode ditulis dalam html

<input type="file" #fileInput>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.