navigationend - title angular 6
Subir archivo en angular? (13)
Sé que esta es una pregunta muy general, pero no puedo cargar un archivo en Angular 2. He intentado
1) http://valor-software.com/ng2-file-upload/ y
2) http://ng2-uploader.com/home
...pero falló. ¿Alguien ha subido un archivo en Angular? ¿Qué método usaste? ¿Cómo hacerlo? Si se proporciona algún código de muestra o enlace de demostración, será realmente apreciado.
Angular 2 proporciona un buen soporte para cargar archivos. No se requiere una biblioteca de terceros.
<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)
)
}
}
utilizando @ angular / core ":" ~ 2.0.0 "y @ angular / http:" ~ 2.0.0 "
Como el código de muestra está un poco desactualizado, pensé en compartir un enfoque más reciente, usando Angular 4.3 y la nueva (er) 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
}
En Angular 2+, es muy importante dejar vacío el Tipo de contenido . Si configura ''Content-Type'' en ''multipart / form-data'', la carga no funcionará.
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)
);
}
}
}
En la forma más simple, el siguiente código funciona en Angular 6/7
this.http.post("http://destinationurl.com/endpoint", fileFormData)
.subscribe(response => {
//handle response
}, err => {
//handle error
});
Aquí está la implementación completa
Esta solución simple funcionó para mí: file-upload.component.html
<div>
<input type="file" #fileInput placeholder="Upload file..." />
<button type="button" (click)="upload()">Upload</button>
</div>
Y luego realice la carga en el componente directamente con 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 está utilizando dotnet core, el nombre del parámetro debe coincidir con el nombre del campo from. archivos en este caso:
[HttpPost("[action]")]
public async Task<IList<FileDto>> UploadFiles(List<IFormFile> files)
{
return await _binaryService.UploadFilesAsync(files);
}
Esta respuesta es un plagio de http://blog.teamtreehouse.com/uploading-files-ajax
Editar : después de cargar, debe borrar la carga del archivo para que el usuario pueda seleccionar un nuevo archivo. Y en lugar de usar XMLHttpRequest, tal vez sea mejor usar 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);
});
}
Gracias a @Eswar. Este código funcionó perfectamente para mí. Quiero agregar ciertas cosas a la solución:
java.io.IOException: RESTEASY007550: Unable to get boundary for multipart
error:
java.io.IOException: RESTEASY007550: Unable to get boundary for multipart
Para resolver este error, debe eliminar el "Contenido-Tipo" "multipart / form-data". Solucionó mi problema.
He subido el archivo con referencia. No se requiere ningún paquete para cargar el archivo de esta manera.
// código que se escribirá en el archivo .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,
});
});
}
}
// código que se escribirá en el archivo 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);
}
// código que se escribirá en html
<input type="file" #fileInput>
He utilizado la siguiente herramienta de cebado con éxito. No tengo skin en el juego con primeNg, solo paso mi sugerencia.
Hoy estaba integrado el ng2-file-upload en mi aplicación angular 6, fue bastante simple, encuentra el siguiente código de alto nivel.
importar el módulo ng2-file-upload
app.module.ts
import { FileUploadModule } from ''ng2-file-upload'';
------
------
imports: [ FileUploadModule ],
------
------
Componente ts importación de archivos 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);
}
------
------
Componente HTML agregar etiqueta de archivo
app.component.html
<input type="file" #fileInput ng2FileSelect [uploader]="uploader" (onFileSelected)="onFileSelected($event)" />
Trabajando en línea stackblitz Link: https://ng2-file-upload-example.stackblitz.io
Ejemplo de código de Stackblitz: https://stackblitz.com/edit/ng2-file-upload-example
Enlace de documentación oficial https://valor-software.com/ng2-file-upload/
Intente no configurar el parámetro de
options
this.http.post(${this.apiEndPoint}, formData)
y asegúrese de no configurar
globalHeaders
en su fábrica Http.
Este es un tutorial útil sobre cómo cargar archivos usando ng2-file-upload y SIN ng2-file-upload.
Para mí me ayuda mucho.
Por el momento, el tutorial contiene un par de errores:
1- El cliente debe tener la misma URL de carga que un servidor, por lo que en
app.component.ts
cambia la línea
const URL = ''http://localhost:8000/api/upload'';
a
const URL = ''http://localhost:3000'';
2- El servidor envía la respuesta como ''text / html'', por lo que en
app.component.ts
cambia
.post(URL, formData).map((res:Response) => res.json()).subscribe(
//map the success function and alert the response
(success) => {
alert(success._body);
},
(error) => alert(error))
a
.post(URL, formData)
.subscribe((success) => alert(''success''), (error) => alert(error));
A partir de las respuestas anteriores, construyo esto con Angular 5.x
Simplemente llame a
uploadFile(url, file).subscribe()
para activar una carga
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);
}
}
Úselo así en su componente
// 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");
}
)
}
Para cargar una imagen con campos de formulario
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);
}
En mi caso, necesitaba .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);
}