Header Ads Widget

Ticker

6/recent/ticker-posts

Carga de varios archivos de imagen con Django 3, Angular 10 y FormData

 

Trabajando con Angular 10, Django 3 y FormData

En este tutorial, veremos cómo usar HTML5 FormData con Angular y django 3 para cargar varios archivos de imagen desde una interfaz de Angular 10 a un servidor Python.

Comencemos clonando un proyecto de django 3 con la carga de un solo archivo que ya estaba implementado.

Clonación de la interfaz de carga de Angular 10

Si no desea seguir los pasos de la parte anterior, primero debe obtener el proyecto que hemos construido. Abra una nueva terminal y ejecute el siguiente comando:

$ git clone https://github.com/techiediaries/django-angular-file-upload-example.git

Luego, navegue dentro de la carpeta del proyecto e instale las dependencias npm usando el siguiente comando:

$ cd django-angular-file-upload-example
$ npm install

A continuación, inicie el servidor de desarrollo usando:

$ ng serve

Su aplicación Angular 10 estará disponible en la 127.0.0.1:4200dirección.

Ejecutando el servidor de carga de Django 3

A continuación, configuremos y ejecutemos nuestro servidor de carga de la API REST de django 3.

Abra una nueva ventana de terminal y cree un entorno virtual usando el siguiente comando:

$ python3 -m venv .env

A continuación, active el entorno virtual usando:

$ source .env/bin/activate

A continuación, navegue hasta el proyecto de backend e instale los paquetes de Python usando:

$ cd django-angular-file-upload-example/backend
$ pip install -r requirements.txt

Finalmente, inicie el servidor de desarrollo usando:

$ python manage.py runserver

Abra su navegador web y navegue hasta la 127.0.0.1:4200/profilepágina donde puede cargar archivos de imagen al servidor:

Carga de archivos de la API REST de Django con Angular 7

Agregar carga de múltiples imágenes con Angular 10, TypeScript y FormData

Ahora, procedamos a implementar la carga de múltiples imágenes.

Como recordatorio, antes de que pueda cargar archivos en su aplicación django, debe configurar MEDIA_URLMEDIA_ROOTen su settings.pyarchivo:

MEDIA_URL  =  '/media/'  
MEDIA_ROOT  =  os.path.join(BASE_DIR,  'media')

Instalando ng2-file-upload

Usaremos la ng2-file-uploadbiblioteca que proporciona directivas fáciles de usar para trabajar con la carga de archivos en Angular 10:

$ npm install --save ng2-file-upload

Importación del módulo de carga de archivos de Angular 10

Después de instalar este paquete, deberá importar FileUploadModuleen su módulo de aplicación Angular 10. Abra el src/app/app.module.tsarchivo y los siguientes cambios:

// [...]
import { FileUploadModule } from 'ng2-file-upload';

@NgModule({
  declarations: [
    AppComponent,
    ProfileComponent
  ],
  imports: [
    // [...]
    FileUploadModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Después de agregar FileUploadModule, podrá usar las siguientes directivas en sus plantillas angulares:

  • La ng2FileDropdirectiva que le permitirá agregar un área donde los usuarios pueden arrastrar y soltar varios archivos,
  • La ng2FileSelectdirectiva que le permitirá agregar un botón de entrada para seleccionar varios archivos.

Agregar la entrada de carga

Abra el src/app/profile/profile.component.htmlarchivo y el siguiente contenido:

<h1>Django 3 REST API with Angular 10 File Upload Example</h1>

<div ng2FileDrop
[ngClass]="{'drop-file-over': hasBaseDropZoneOver}"
(fileOver)="fileOverBase($event)"
[uploader]="uploader"
class="area">
<div id="dropZone">Drop files here</div>
</div>

<input type="file" ng2FileSelect [uploader]="uploader" multiple  />

Agregamos la ng2FileDropdirectiva al <div>que representa el área de colocación y la ng2FileSelectdirectiva al campo de entrada del archivo. También agregamos la multiplepalabra clave a la entrada del archivo para permitir a los usuarios seleccionar varios archivos.

También usamos ngClasspara agregar una clase CSS dinámica al área de colocación que se activa cuando se arrastra un archivo sobre el área y lo vinculamos a la hasBaseDropZoneOvervariable que definirá en el componente.

Vinculamos el fileOverevento a un fileOverBase()método que también definiremos en el componente. Esto se llamará cuando se arrastre un archivo sobre el área de colocación.

También vinculamos la uploaderpropiedad a un uploaderobjeto que también definiremos en el componente. Este objeto se utiliza para rastrear los archivos seleccionados y soltados que se cargarán.

A continuación, agregamos un botón para cargar los archivos y una lista para mostrar los archivos que se cargarán:

<button (click)="upload()">Upload files</button>

<h2>Your files: {{ uploader?.queue?.length }}</h2>
<ul>
<li *ngFor="let item of uploader.queue">
    {{ item?.file?.name }}
</li>
</ul>

A continuación, abra el src/app/profile/profile.component.tsarchivo y comience agregando las siguientes importaciones:

// [...]
import { UploadService } from '../upload.service';
import { FileUploader, FileLikeObject } from 'ng2-file-upload';
import { concat } from  'rxjs';

A continuación, defina las siguientes variables:

  DJANGO_SERVER = 'http://127.0.0.1:8000';
  public uploader: FileUploader = new FileUploader({});
  public hasBaseDropZoneOver: boolean = false;

A continuación, defina el fileOverBase()método al que se llama cuando se arrastra un archivo sobre el área de colocación:

fileOverBase(event):  void {
    this.hasBaseDropZoneOver  =  event;
}

La eventvariable es igual truecuando el archivo se encuentra sobre el área base del área de colocación.

A continuación, defina el getFiles()método que devuelve la matriz de archivos en la uploadercola:

  getFiles(): FileLikeObject[] {
    return this.uploader.queue.map((fileItem) => {
      return fileItem.file;
    });
  }

Agregar el método de carga de TypeScript

Finalmente, agregue el upload()método al que se llamará para cargar realmente los archivos al servidor Django usando HttpClientFormData:


  upload() {   
    let files = this.getFiles();
    console.log(files);
    let requests = [];
    files.forEach((file) => {
      let formData = new FormData();
      formData.append('file' , file.rawFile, file.name);
      requests.push(this.uploadService.upload(formData));     
    });

    concat(...requests).subscribe(
      (res) => {
        console.log(res);
      },
      (err) => {  
        console.log(err);
      }
    );
  }

Llamamos al getFiles()método para obtener una matriz de todos los archivos seleccionados y soltados. A continuación, iteramos sobre la matriz de archivos de imagen y creamos un FormDataobjeto.

A continuación, agregamos el archivo actual en el bucle al FormDataobjeto y llamamos al upload()método de nuestro, UploadServiceluego empujamos el Observable devuelto a la requestsmatriz.

Este es otro ejemplo del uso de FormData y TypeScript .

Finalmente usamos el concat()operador RxJS para concatenar todos los Observables devueltos y suscribirnos a cada uno de ellos secuencialmente para enviar múltiples solicitudes POST al servidor.

Nota : En nuestro ejemplo, creamos un FormDataobjeto para cada archivo de la filesmatriz. En teoría, podríamos crear solo un FormDataobjeto y agregar todos los archivos en él usando []la clave, es decir formData.append('file[]' , file.rawFile, file.name);, enviar solo una solicitud al servidor Django para cargar todos los archivos adjuntos al FormDataobjeto (Ver FormData.append () ) pero esto no ' ¡Parece que funciona para nosotros! (¿Quizás por TypeScript?).

Usaremos el estilo CSS de este codepen . Abra el src/app/profile/profile.component.cssarchivo y agregue:

.area {
      width: 77%;
      padding: 15px;
      margin: 15px;
      border: 1px solid #333;
      background: rgba(0,0,0,0.7);
}

#dropZone {
      border: 2px dashed #bbb;
      -webkit-border-radius: 5px;
      border-radius: 5px;
      padding: 50px;
      text-align: center;
      font: 21pt bold arial;
      color: #bbb;
}

.drop-file-over{
    background: #333;
}

Esta es una captura de pantalla de la página después de seleccionar y cargar un montón de archivos:

Carga de archivos múltiples de Angular 7 Django

Comprensión FormData

Normalmente, al enviar datos a través de un formulario, se codificarán con el application/x-www-form-urlencodedtipo de codificación. Excepto cuando necesite utilizar un campo de entrada de archivo (es decir <input type="file">) en su formulario; en este caso, debe utilizar el multipart/form-datatipo de codificación.

Se multipart/form-datapuede utilizar para enviar tipos de datos complejos, como archivos. Los datos se envían como pares clave / valor donde cada valor está asociado con una clave.

HTML5 proporciona la FormDatainterfaz que equivale a utilizar un multipart/form-dataformulario. Esta interfaz es útil cuando desea enviar datos de formularios de varias partes con Ajax o HttpClient en el caso de Angular, por lo que en lugar de crear un formulario con el multipart/form-datatipo, creamos una instancia de FormDatay usamos el append()método para agregar pares clave / valor.

Conclusión

En este tutorial, hemos visto un ejemplo de carga de varios archivos de imagen con Angular 10 y django 3.

Publicar un comentario

0 Comentarios