Angular File Upload

后端 未结 12 1997
名媛妹妹
名媛妹妹 2020-11-22 10:04

I\'m a beginner with Angular, I want to know how to create Angular 5 File upload part, I\'m trying to find any tutorial or doc, but I don\'t see anything a

相关标签:
12条回答
  • 2020-11-22 10:53

    Very easy and fastest method is using ng2-file-upload.

    Install ng2-file-upload via npm. npm i ng2-file-upload --save

    At first import module in your module.

    import { FileUploadModule } from 'ng2-file-upload';
    
    Add it to [imports] under @NgModule:
    imports: [ ... FileUploadModule, ... ]
    

    Markup:

    <input ng2FileSelect type="file" accept=".xml" [uploader]="uploader"/>
    

    In your commponent ts:

    import { FileUploader } from 'ng2-file-upload';
    ...
    uploader: FileUploader = new FileUploader({ url: "api/your_upload", removeAfterUpload: false, autoUpload: true });
    

    It`is simplest usage of this. To know all power of this see demo

    0 讨论(0)
  • 2020-11-22 10:53

    Here is how I did it to upload the excel files:
    Directory structure:

    app
    |-----uploadcomponent
               |-----uploadcomponent.module.ts
               |-----uploadcomponent.html
    |-----app.module.ts
    |-----app.component.ts
    |-----app.service.ts
    

    uploadcomponent.html

    <div>
       <form [formGroup]="form" (ngSubmit)="onSubmit()">
         <input type="file" name="profile"  enctype="multipart/form-data" accept=".xlsm,application/msexcel" (change)="onChange($event)" />
         <button type="submit">Upload Template</button>
         <button id="delete_button" class="delete_button" type="reset"><i class="fa fa-trash"></i></button> 
       </form>           
    </div>
    

    uploadcomponent.ts

        import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
        import { Component, OnInit } from '@angular/core';
        ....
        export class UploadComponent implements OnInit {
            form: FormGroup;
            constructor(private formBuilder: FormBuilder, private uploadService: AppService) {}
            ngOnInit() {  
                this.form = this.formBuilder.group({
                   profile: ['']
                });
            }
    
            onChange(event) {
                if (event.target.files.length > 0) {
                  const file = event.target.files[0];
    
                  this.form.get('profile').setValue(file);
                  console.log(this.form.get('profile').value)
                }
            }
    
            onSubmit() {
               const formData = new FormData();
               formData.append('file', this.form.get('profile').value);
    
               this.uploadService.upload(formData).subscribe(
                 (res) => {
                   this.response = res;
    
                   console.log(res);
    
                 },
                 (err) => {  
                   console.log(err);
                 });
             }
        }
    

    app.service.ts

        upload(formData) {
            const endpoint = this.service_url+'upload/';
            const httpOptions = headers: new HttpHeaders({    <<<< Changes are here
                'Authorization': 'token xxxxxxx'})
            };
            return this.http.post(endpoint, formData, httpOptions);
        }
    

    In Backend I use DJango REST Framework.
    models.py

    from __future__ import unicode_literals
    from django.db import models
    from django.db import connection
    from django_mysql.models import JSONField, Model
    import uuid
    import os
    
    
    def change_filename(instance, filename):
        extension = filename.split('.')[-1]
        file_name = os.path.splitext(filename)[0]
        uuid_name = uuid.uuid4()
        return file_name+"_"+str(uuid_name)+"."+extension
    
    class UploadTemplate (Model):
        id = models.AutoField(primary_key=True)
        file = models.FileField(blank=False, null=False, upload_to=change_filename)
    
        def __str__(self):
            return str(self.file.name)
    

    views.py.

    class UploadView(APIView):
        serializer_class = UploadSerializer
        parser_classes = [MultiPartParser]       
    
        def get_queryset(self):
            queryset = UploadTemplate.objects.all()
            return queryset
    
        def post(self, request, *args, **kwargs):
            file_serializer = UploadSerializer(data=request.data)
            status = None
            message = None
            if file_serializer.is_valid():
                file_serializer.save()
                status = "Success"
                message = "Success"
            else:
                status = "Failure"
                message = "Failure!"
            content = {'status': status, 'message': message}
            return Response(content)
    

    serializers.py.

    from uploadtemplate.models import UploadTemplate
    from rest_framework import serializers
    
    class UploadSerializer(serializers.ModelSerializer):
        class Meta:
            model = UploadTemplate
            fields = '__all__'   
    

    urls.py.

    router.register(r'uploadtemplate', uploadtemplateviews.UploadTemplateView, 
        base_name='UploadTemplate')
    urlpatterns = [
        ....
        url(r'upload/', uploadtemplateviews.UploadTemplateView.as_view()),
    ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    
    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    

    MEDIA_URL and MEDIA_ROOT is defined in settings.py of the project.

    Thanks!

    0 讨论(0)
  • 2020-11-22 10:55

    This way I implement upload file to web API in project.

    I share for whom concern.

    const formData: FormData = new FormData();
    formData.append('Image', image, image.name);
    formData.append('ComponentId', componentId);
    return this.http.post('/api/dashboard/UploadImage', formData);
    

    Step by step

    ASP.NET Web API

    [HttpPost]
    [Route("api/dashboard/UploadImage")]
    public HttpResponseMessage UploadImage() 
    {
        string imageName = null;
        var httpRequest = HttpContext.Current.Request;
        //Upload Image
        var postedFile = httpRequest.Files["Image"];
        //Create custom filename
        if (postedFile != null)
        {
            imageName = new String(Path.GetFileNameWithoutExtension(postedFile.FileName).Take(10).ToArray()).Replace(" ", "-");
            imageName = imageName + DateTime.Now.ToString("yymmssfff") + Path.GetExtension(postedFile.FileName);
            var filePath = HttpContext.Current.Server.MapPath("~/Images/" + imageName);
            postedFile.SaveAs(filePath);
        }
    }
    

    HTML form

    <form #imageForm=ngForm (ngSubmit)="OnSubmit(Image)">
    
        <img [src]="imageUrl" class="imgArea">
        <div class="image-upload">
            <label for="file-input">
                <img src="upload.jpg" />
            </label>
    
            <input id="file-input" #Image type="file" (change)="handleFileInput($event.target.files)" />
            <button type="submit" class="btn-large btn-submit" [disabled]="Image.value=='' || !imageForm.valid"><i
                    class="material-icons">save</i></button>
        </div>
    </form>
    

    TS file to use API

    OnSubmit(Image) {
        this.dashboardService.uploadImage(this.componentId, this.fileToUpload).subscribe(
          data => {
            console.log('done');
            Image.value = null;
            this.imageUrl = "/assets/img/logo.png";
          }
        );
      }
    

    Service TS

    uploadImage(componentId, image) {
            const formData: FormData = new FormData();
            formData.append('Image', image, image.name);
            formData.append('ComponentId', componentId);
            return this.http.post('/api/dashboard/UploadImage', formData);
        }
    
    0 讨论(0)
  • 2020-11-22 10:56

    Complete example of File upload using Angular and nodejs(express)

    HTML Code

                <div class="form-group">
                    <label for="file">Choose File</label><br/>
                    <input type="file" id="file" (change)="uploadFile($event.target.files)" multiple>
                </div>
    

    TS Component Code

    uploadFile(files) {
        console.log('files', files)
            var formData = new FormData();
    
        for(let i =0; i < files.length; i++){
          formData.append("files", files[i], files[i]['name']);
            }
    
        this.httpService.httpPost('/fileUpload', formData)
          .subscribe((response) => {
            console.log('response', response)
          },
            (error) => {
          console.log('error in fileupload', error)
           })
      }
    

    Node Js code

    fileUpload API controller

    function start(req, res) {
    fileUploadService.fileUpload(req, res)
        .then(fileUploadServiceResponse => {
            res.status(200).send(fileUploadServiceResponse)
        })
        .catch(error => {
            res.status(400).send(error)
        })
    }
    
    module.exports.start = start
    

    Upload service using multer

    const multer = require('multer') // import library
    const moment = require('moment')
    const q = require('q')
    const _ = require('underscore')
    const fs = require('fs')
    const dir = './public'
    
    /** Store file on local folder */
    let storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'public')
    },
    filename: function (req, file, cb) {
        let date = moment(moment.now()).format('YYYYMMDDHHMMSS')
        cb(null, date + '_' + file.originalname.replace(/-/g, '_').replace(/ /g,     '_'))
    }
    })
    
    /** Upload files  */
    let upload = multer({ storage: storage }).array('files')
    
    /** Exports fileUpload function */
    module.exports = {
    fileUpload: function (req, res) {
        let deferred = q.defer()
    
        /** Create dir if not exist */
        if (!fs.existsSync(dir)) {
            fs.mkdirSync(dir)
            console.log(`\n\n ${dir} dose not exist, hence created \n\n`)
        }
    
        upload(req, res, function (err) {
            if (req && (_.isEmpty(req.files))) {
                deferred.resolve({ status: 200, message: 'File not attached', data: [] })
            } else {
                if (err) {
                    deferred.reject({ status: 400, message: 'error', data: err })
                } else {
                    deferred.resolve({
                        status: 200,
                        message: 'File attached',
                        filename: _.pluck(req.files,
                            'filename'),
                        data: req.files
                    })
                }
            }
        })
        return deferred.promise
    }
    }
    
    0 讨论(0)
  • 2020-11-22 10:59

    Personally I'm doing this using ngx-material-file-input for the front-end, and Firebase for the back-end. More precisely Cloud Storage for Firebase for the back-end combined with Cloud Firestore. Below an example, which limits file to be not larger than 20 MB, and accepts only certain file extensions. I'm also using Cloud Firestore for storing links to the uploaded files, but you can skip this.

    contact.component.html

    <mat-form-field>
      <!--
        Accept only files in the following format: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx. However, this is easy to bypass, Cloud Storage rules has been set up on the back-end side.
      -->
      <ngx-mat-file-input
        [accept]="[
          '.doc',
          '.docx',
          '.jpg',
          '.jpeg',
          '.pdf',
          '.png',
          '.xls',
          '.xlsx'
        ]"
        (change)="uploadFile($event)"
        formControlName="fileUploader"
        multiple
        aria-label="Here you can add additional files about your project, which can be helpeful for us."
        placeholder="Additional files"
        title="Additional files"
        type="file"
      >
      </ngx-mat-file-input>
      <mat-icon matSuffix>folder</mat-icon>
      <mat-hint
        >Accepted formats: DOC, DOCX, JPG, JPEG, PDF, PNG, XLS and XLSX,
        maximum files upload size: 20 MB.
      </mat-hint>
      <!--
        Non-null assertion operators are required to let know the compiler that this value is not empty and exists.
      -->
      <mat-error
        *ngIf="contactForm.get('fileUploader')!.hasError('maxContentSize')"
      >
        This size is too large,
        <strong
          >maximum acceptable upload size is
          {{
            contactForm.get('fileUploader')?.getError('maxContentSize')
              .maxSize | byteFormat
          }}</strong
        >
        (uploaded size:
        {{
          contactForm.get('fileUploader')?.getError('maxContentSize')
            .actualSize | byteFormat
        }}).
      </mat-error>
    </mat-form-field>
    

    contact.component.ts (size validator part)

    import { FileValidator } from 'ngx-material-file-input';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    
    /**
     * @constructor
     * @description Creates a new instance of this component.
     * @param  {formBuilder} - an abstraction class object to create a form group control for the contact form.
     */
    constructor(
      private angularFirestore: AngularFirestore,
      private angularFireStorage: AngularFireStorage,
      private formBuilder: FormBuilder
    ) {}
    
    public maxFileSize = 20971520;
    public contactForm: FormGroup = this.formBuilder.group({
        fileUploader: [
          '',
          Validators.compose([
            FileValidator.maxContentSize(this.maxFileSize),
            Validators.maxLength(512),
            Validators.minLength(2)
          ])
        ]
    })
    

    contact.component.ts (file uploader part)

    import { AngularFirestore } from '@angular/fire/firestore';
    import {
      AngularFireStorage,
      AngularFireStorageReference,
      AngularFireUploadTask
    } from '@angular/fire/storage';
    import { catchError, finalize } from 'rxjs/operators';
    import { throwError } from 'rxjs';
    
    public downloadURL: string[] = [];
    /**
    * @description Upload additional files to Cloud Firestore and get URL to the files.
       * @param {event} - object of sent files.
       * @returns {void}
       */
      public uploadFile(event: any): void {
        // Iterate through all uploaded files.
        for (let i = 0; i < event.target.files.length; i++) {
          const randomId = Math.random()
            .toString(36)
            .substring(2); // Create random ID, so the same file names can be uploaded to Cloud Firestore.
    
          const file = event.target.files[i]; // Get each uploaded file.
    
          // Get file reference.
          const fileRef: AngularFireStorageReference = this.angularFireStorage.ref(
            randomId
          );
    
          // Create upload task.
          const task: AngularFireUploadTask = this.angularFireStorage.upload(
            randomId,
            file
          );
    
          // Upload file to Cloud Firestore.
          task
            .snapshotChanges()
            .pipe(
              finalize(() => {
                fileRef.getDownloadURL().subscribe((downloadURL: string) => {
                  this.angularFirestore
                    .collection(process.env.FIRESTORE_COLLECTION_FILES!) // Non-null assertion operator is required to let know the compiler that this value is not empty and exists.
                    .add({ downloadURL: downloadURL });
                  this.downloadURL.push(downloadURL);
                });
              }),
              catchError((error: any) => {
                return throwError(error);
              })
            )
            .subscribe();
        }
      }
    

    storage.rules

    rules_version = '2';
    service firebase.storage {
      match /b/{bucket}/o {
        match /{allPaths=**} {
            allow read; // Required in order to send this as attachment.
          // Allow write files Firebase Storage, only if:
          // 1) File is no more than 20MB
          // 2) Content type is in one of the following formats: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx.
          allow write: if request.resource.size <= 20 * 1024 * 1024
            && (request.resource.contentType.matches('application/msword')
            || request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
            || request.resource.contentType.matches('image/jpg')
            || request.resource.contentType.matches('image/jpeg')
            || request.resource.contentType.matches('application/pdf')
                    || request.resource.contentType.matches('image/png')
            || request.resource.contentType.matches('application/vnd.ms-excel')
            || request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
        }
      }
    }
    
    0 讨论(0)
  • 2020-11-22 11:00

    I am using Angular 5.2.11, I like the solution provided by Gregor Doroschenko, however I noticed that the uploaded file is of zero bytes, I had to make a small change to get it to work for me.

    postFile(fileToUpload: File): Observable<boolean> {
      const endpoint = 'your-destination-url';
      return this.httpClient
        .post(endpoint, fileToUpload, { headers: yourHeadersConfig })
        .map(() => { return true; })
        .catch((e) => this.handleError(e));
    }
    

    The following lines (formData) didn't work for me.

    const formData: FormData = new FormData();
    formData.append('fileKey', fileToUpload, fileToUpload.name);
    

    https://github.com/amitrke/ngrke/blob/master/src/app/services/fileupload.service.ts

    0 讨论(0)
提交回复
热议问题