อัพโหลดไฟล์เป็นมุมหรือไม่


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 ได้รับอาเรย์ / วัตถุว่างเปล่า
Kaleem Ullah

20
มันใช้งานได้สำหรับฉันยกเว้น - ฉันต้องทำงานกับบรรทัดนี้ - headers.append('enctype', 'multipart/form-data');(ใช้ 'enctype' เพื่อแทนที่ 'ประเภทเนื้อหา') อาจขึ้นอยู่กับรหัสฝั่งเซิร์ฟเวอร์ (ie api)
Ariful Islam

29
ทำได้ดีมากหากทีม Angular จะเขียนเอกสารบางอย่างเกี่ยวกับเรื่องนั้นฉันไม่สามารถหาบรรทัดเดียวในเอกสารของพวกเขาได้ ตัวอย่างโค้ดนี้ล้าสมัยและไม่ทำงานกับ v4 +
Rob B

10
หมายเหตุสำหรับบางแอปพลิเคชันเซิร์ฟเวอร์การตั้งค่าประเภทเนื้อหาจะถูกปฏิเสธ คุณต้องปล่อยให้มันว่างเปล่า: let headers = new Headers (); เบราว์เซอร์จะจัดเรียงทุกอย่างให้คุณ
PeterS

6
LMFAO พยายาม 20 นาทีกับอึนี้จนกระทั่งฉันรู้ว่าฉันไม่จำเป็นต้องตั้งส่วนหัวเลย หมายเหตุถึงผู้อื่นที่ใช้เชิงมุม 4.xx กับ. web web อย่าพยายามตั้งค่าส่วนหัว! ขอบคุณสำหรับการชี้ให้เห็นว่า @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 ขอบคุณ. และคุณต้องการห้องสมุดเหล่านี้เพื่อนำเข้า นำเข้า {HttpClient, HttpParams, HttpRequest, HttpEvent, HttpEventType, HttpResponse} จาก '@ angular / common / http';
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

เพื่อที่จะแก้ไขข้อผิดพลาดนี้คุณควรลบ "หลายประเภทเนื้อหา" "หลายส่วน / แบบฟอร์มข้อมูล" มันแก้ไขปัญหาของฉัน


5
+1 หากคุณลบประเภทเนื้อหาเนื้อหานั้นจะถูกสร้างขึ้นอย่างถูกต้อง multipart/form-data; boundary=---------------------------186035562730765173675680113เช่น: ดูstackoverflow.com/a/29697774/1475331และgithub.com/angular/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 จากแบ็กเอนด์แทน เรากำลังใช้สปริงและแองกูลาร์ 2. ความช่วยเหลือใด ๆ ที่ชื่นชม
เฮเลน

นี่ควรเป็นเพียงความเห็นต่อคำตอบของเขาใช่ไหม?
MMalke

19

เนื่องจากตัวอย่างโค้ดล้าสมัยเล็กน้อยฉันคิดว่าฉันจะแบ่งปันวิธีการใหม่กว่าโดยใช้ Angular 4.3 และ HttpClient API ใหม่ (er), @ 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

ดูที่ข้อมูลในฟอร์มหลายส่วนwebdavsystem.com/javaserver/doc/resumable_upload/multipart_post
jsaddwater

15

ใน Angular 2+ เป็นสิ่งสำคัญมากที่จะปล่อยให้Content-Typeว่างเปล่า หากคุณตั้งค่า 'ประเภทเนื้อหา' เป็น 'หลายส่วน / แบบฟอร์มข้อมูล' การอัปโหลดจะไม่ทำงาน!

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

8

ฉันได้ใช้เครื่องมือต่อไปนี้จากการทำสำเร็จ ฉันไม่มีสกินในเกมที่มี PrimeNg เพียงแค่ส่งข้อเสนอแนะของฉัน

http://www.primefaces.org/primeng/#/fileupload


กรุณาช่วยบอกให้เรารู้ว่ามันรองรับ NG2 หรือไม่?
G1P

@ G1P มันรองรับ Angular 4 อย่างแน่นอน primefaces.org/primeng/#/setup
makkasi

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

}

หากคุณใช้ดอทเน็ตคอร์ชื่อพารามิเตอร์ต้องตรงกับจากชื่อฟิลด์ ไฟล์ในกรณีนี้:

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

คำตอบนี้เป็นคำจำนวนมากของhttp://blog.teamtreehouse.com/uploading-files-ajax

แก้ไข : หลังจากอัปโหลดคุณต้องล้างไฟล์ที่อัปโหลดเพื่อให้ผู้ใช้สามารถเลือกไฟล์ใหม่ และแทนที่จะใช้ XMLHttpRequest อาจเป็นการดีกว่าถ้าใช้การดึงข้อมูล:

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

สำหรับฉันมันช่วยได้มาก

ในขณะนี้การสอนมีข้อผิดพลาดสองประการ:

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

ในกรณีของฉันฉันต้องการ. NET Web Api ใน 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

วันนี้ฉันรวมng2- ไฟล์ - อัพโหลดเข้ากับแอปพลิเคชันมุมของฉัน 6 มันค่อนข้างง่ายโปรดหารหัสระดับสูงด้านล่าง

นำเข้าng2-file-uploadโมดูล

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 Link: 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)

และตรวจสอบให้แน่ใจว่าคุณไม่ได้ตั้งค่าglobalHeadersในโรงงาน Http ของคุณ



1

jspdf และ Angular 8

ฉันสร้างไฟล์ PDF และต้องการอัปโหลดไฟล์ PDF ด้วยคำขอ POST นี่เป็นวิธีที่ฉันทำ (เพื่อความชัดเจนฉันจะลบโค้ดและเลเยอร์บริการบางส่วน)

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

}

// code ที่จะเขียนเป็น html

<input type="file" #fileInput>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.