Je sais que la question est très générale, mais je ne parviens pas à télécharger un fichier dans Angular 2. J'ai essayé
1) http://valor-software.com/ng2-file-upload/ et
2) http://ng2-uploader.com/home
...mais a échoué. Quelqu'un a-t-il téléchargé un fichier dans Angular? Quelle méthode avez-vous utilisée? Comment le faire Si un exemple de code ou un lien de démonstration est fourni, il sera vraiment apprécié.
Angular 2 fournit un bon support pour le téléchargement de fichiers. Aucune bibliothèque tierce n'est requise.
<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)
)
}
}
using @ angular/core ":" ~ 2.0.0 "et @ angular/http:" ~ 2.0.0 "
D'après les réponses ci-dessus, je construis cela avec Angular 5.x
Il suffit d'appeler uploadFile(url, file).subscribe()
pour déclencher un téléchargement.
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);
}
}
Utilisez-le comme ceci dans votre composant
// 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");
}
)
}
Merci à Eswar. Ce code a parfaitement fonctionné pour moi. Je veux ajouter certaines choses à la solution:
Je devenais erreur: Java.io.IOException: RESTEASY007550: Unable to get boundary for multipart
Afin de résoudre cette erreur, vous devez supprimer le "Content-Type" "multipart/form-data". Cela a résolu mon problème.
Comme l’exemple de code est un peu obsolète, j’ai pensé partager une approche plus récente, en utilisant Angular 4.3 et la nouvelle (plus) API HttpClient, @ 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
}
Dans Angular 2+, il est très important de laisser le Content-Type vide. Si vous définissez 'Content-Type' sur 'multipart/form-data', le téléchargement ne fonctionnera pas!
pload.component.html
<input type="file" (change)="fileChange($event)" name="file" />
pload.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)
);
}
}
}
J'ai utilisé l'outil suivant d'amorçage avec succès. Je n'ai pas de peau dans le jeu avec PrimeNg, je ne fais que transmettre ma suggestion.
Cette solution simple a fonctionné pour moi: file-upload.component.html
<div>
<input type="file" #fileInput placeholder="Upload file..." />
<button type="button" (click)="upload()">Upload</button>
</div>
Et ensuite, téléchargez directement le composant avec 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);
}
}
}
Si vous utilisez dotnet core, le nom du paramètre doit correspondre au nom du champ from. fichiers dans ce cas:
[HttpPost("[action]")]
public async Task<IList<FileDto>> UploadFiles(List<IFormFile> files)
{
return await _binaryService.UploadFilesAsync(files);
}
Cette réponse est un plagiat de http://blog.teamtreehouse.com/uploading-files-ajax
Modifier : après le téléchargement, vous devez effacer le téléchargement de fichier afin que l'utilisateur puisse sélectionner un nouveau fichier. Et au lieu d'utiliser XMLHttpRequest, il vaut peut-être mieux utiliser 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);
});
}
Ceci est un tutoriel utile , comment télécharger un fichier en utilisant ng2-file-upload et WITHOUT ng2-file-upload.
Pour moi ça aide beaucoup.
Pour le moment, le tutoriel contient quelques erreurs:
1- Le client doit avoir la même URL de téléchargement qu'un serveur, donc dans app.component.ts
changez de ligne
const URL = 'http://localhost:8000/api/upload';
à
const URL = 'http://localhost:3000';
2- Le serveur envoie sa réponse sous la forme 'text/html', donc dans app.component.ts
change
.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));
Pour télécharger une image avec des champs de formulaire
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);
}
Dans mon cas, j'avais besoin de .NET Web Api en 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);
}
Aujourd'hui, j'ai été intégré ng2-file-upload package à mon application angular 6, c'était assez simple, veuillez trouver le code de haut niveau ci-dessous.
importer le module ng2-file-upload
app.module.ts
import { FileUploadModule } from 'ng2-file-upload';
------
------
imports: [ FileUploadModule ],
------
------
Composant ts fichier import 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);
}
------
------
Composant HTML Ajouter une balise de fichier
app.component.html
<input type="file" #fileInput ng2FileSelect [uploader]="uploader" (onFileSelected)="onFileSelected($event)" />
Travailler en ligne stackblitz Lien: https://ng2-file-upload-example.stackblitz.io
Exemple de code Stackblitz: https://stackblitz.com/edit/ng2-file-upload-example
Lien à la documentation officielle https://valor-software.com/ng2-file-upload/
Dans sa forme la plus simple, le code suivant fonctionne sous Angular 6/7
this.http.post("http://destinationurl.com/endpoint", fileFormData)
.subscribe(response => {
//handle response
}, err => {
//handle error
});
Voici le implémentation complète
Essayez de ne pas régler le paramètre options
this.http.post(${this.apiEndPoint}, formData)
et assurez-vous de ne pas régler le paramètre globalHeaders
dans votre fabrique Http.
J'ai téléchargé le fichier en utilisant une référence. Aucun paquet n'est requis pour télécharger le fichier de cette façon.
// code à écrire dans un fichier .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,
});
});
}
}
// code à écrire dans le fichier 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 à écrire en html
<input type="file" #fileInput>