6

I need to upload file using angular 2. I used it at client side and I used a Web Api at server side. How can I use this combination to implement it?

2

2 Answers 2

9

I successfully uploaded files with Angular2 and ASP.NET Core.

I realize your backend is not exactly the same, but I think it might put you in the right direction.

I used ng2-file-upload from valor-software

Install it with npm install, add it to your package folder, configure it with systemjs or webpack. I use angular-cli webpack so the only config I did manually is in the component file.

Frontend Angular2

import { Component, Input } from '@angular/core';
import { NgClass, NgStyle } from '@angular/common';

import {FILE_UPLOAD_DIRECTIVES, FileUploader, Headers} from 'ng2-file-upload/ng2-file-upload';


const URL = 'http://localhost:49513/api/values/';

@Component({
  selector: '...',
  templateUrl: '...',
  providers: [...],
  directives: [FILE_UPLOAD_DIRECTIVES, NgClass, NgStyle]
})

export class ProjectDetailsComponent {

  public myHeaders: Headers[] = [];


  public uploader:FileUploader = new FileUploader(
  {
      url: URL,
      headers: <Headers[]> [
        { name: 'Content-Type', value: 'multipart/form-data' }
      ]
  });

  public hasBaseDropZoneOver:boolean    = false;
  public hasAnotherDropZoneOver:boolean = false;

  ...

  public fileOverBase(e:any):void {
    this.hasBaseDropZoneOver = e;
  }

  public fileOverAnother(e:any):void {
    this.hasAnotherDropZoneOver = e;
  }

  ...
}

Backend using ASP.NET Core

[HttpPost]
public async Task<ActionResult> Post(IFormFile file)
{
    try
    {
        if (file != null && file.Length > 0)
        {
            var savePath = Path.Combine(_appEnvironment.WebRootPath, "uploads", file.FileName);

            using (var fileStream = new FileStream(savePath, FileMode.Create))
            {
                await file.CopyToAsync(fileStream);
            }

            return Created(savePath, file)
        }
        return BadRequest();
    }
    catch (Exception)
    {
        return StatusCode(500, ex.Message);
    }

}

Bonus: I edited their html to use Material2 instead of bootstrap.

<div class="container">

      <div class="navbar navbar-default">
          <div class="navbar-header">
              <a class="navbar-brand" href>Angular2 File Upload</a>
          </div>
      </div>

      <div class="row">

          <div class="col-md-3">

              <h3>Select files</h3>

              <div ng2FileDrop
                  [ngClass]="{'nv-file-over': hasBaseDropZoneOver}"
                  (fileOver)="fileOverBase($event)"
                  [uploader]="uploader"
                  class="well my-drop-zone">
                  Base drop zone
              </div>

          </div>

          <div class="col-md-9" style="margin-bottom: 40px">

                <h3>Upload queue</h3>
                <p>Queue length: {{ uploader?.queue?.length }}</p>

                <table class="table">
                    <thead>
                    <tr>
                        <th width="50%">Name</th>
                        <th>Size</th>
                        <th>Progress</th>
                        <th>Status</th>
                        <th>Actions</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr *ngFor="let item of uploader.queue">


                        <td><strong>{{ item?.file?.name }} {{item?.progress}} %</strong></td>
                        <td nowrap>{{ (item?.file?.size/1024/1024).toFixed(2) }} MB</td>
                        <td>
                            <div class="progress" style="margin-bottom: 0;">

                                <md-progress-bar mode="determinate" value="{{item.progress}}"></md-progress-bar>

                            </div>
                        </td>


                        <td class="text-center">
                            <span *ngIf="item.isSuccess"><i class="glyphicon glyphicon-ok"></i></span>
                            <span *ngIf="item.isCancel"><i class="glyphicon glyphicon-ban-circle"></i></span>
                            <span *ngIf="item.isError"><i class="glyphicon glyphicon-remove"></i></span>
                        </td>
                        <td nowrap>
                            <button type="button" class="btn btn-success btn-xs"
                                    (click)="item.upload()" [disabled]="item.isReady || item.isUploading || item.isSuccess">
                                <span class="glyphicon glyphicon-upload"></span> Upload
                            </button>
                            <button type="button" class="btn btn-warning btn-xs"
                                    (click)="item.cancel()" [disabled]="!item.isUploading">
                                <span class="glyphicon glyphicon-ban-circle"></span> Cancel
                            </button>
                            <button type="button" class="btn btn-danger btn-xs"
                                    (click)="item.remove()">
                                <span class="glyphicon glyphicon-trash"></span> Remove
                            </button>
                        </td>
                    </tr>
                    </tbody>
                </table>

              <div>
                  <div>
                      Queue progress:
                      <div class="progress" style="">
                          <div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': uploader.progress + '%' }"></div>
                      </div>
                  </div>

                  <button (click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length" md-raised-button class="md-raised md-primary">Upload all</button>
                  <button (click)="uploader.cancelAll()" [disabled]="!uploader.isUploading" md-raised-button class="md-raised md-warn">Cancel all</button>
                  <button (click)="uploader.clearQueue()" [disabled]="!uploader.queue.length" md-raised-button class="md-accent md-hue-1">Remove all</button>


              </div>
          </div>
      </div>
  </div>
Sign up to request clarification or add additional context in comments.

5 Comments

I am getting the following error while installing it, new to angular, can you please help? npm ERR! peerinvalid The package [email protected] does not satisfy its siblings' peerDependencies requirements! npm ERR! peerinvalid Peer [email protected] wants [email protected] npm ERR! peerinvalid Peer @angular/[email protected] wants [email protected]
Is there a way to get server response on file uploaded ?
Above code is compatible with the latest release/ v2.1.0 of angular?
Thanks for the excellent answer. This must get more reputations :) One question : Do you know how to implement the delete functionality with it ? at this moment it is just a client side operation.Do you know how to handle it with asp.net core ? specially we need to tackle the delete method on ng2-file-upload.how can we do that ?
Does anyone know if this still works? It looks like 'directives' is no longer a part of the @component decorator.
1

For material 2 edited more... @Dave thanks for answer

<style>
    .box.has-advanced-upload {
        background-color: white;
        outline: 2px dashed black;
        outline-offset: -10px;
        height: 100px;
        vertical-align: middle;
        text-align: center;
        line-height: 100px;
    }

        .box.has-advanced-upload .box__dragndrop {
            display: inline;
        }

    .my-drop-zone {
        border: dotted 3px lightgray;
    }

    .nv-file-over {
        border: dotted 3px red;
    }
    /* Default class applied to drop zones on over */
    .another-file-over-class {
        border: dotted 3px green;
    }
</style>
<md-card class="detail-card">
    <md-card-header>
        <md-card-title>
            <h3>Dosya Yükle</h3>
        </md-card-title>
    </md-card-header>
    <md-card-content>
        <div fxLayout="column">
            <div fxLayout="row">
                <div fxLayout="column">
                    <input type="file" ng2FileSelect [uploader]="uploader" multiple /><br />
                    <input type="file" ng2FileSelect [uploader]="uploader" />

                </div>
                <div fxFlex>
                    <h5>Select files</h5>
                    <div ng2FileDrop
                         [ngClass]="{'nv-file-over': hasBaseDropZoneOver}"
                         (fileOver)="fileOverBase($event)"
                         [uploader]="uploader"
                         class="well my-drop-zone box has-advanced-upload">
                        Sürükle bırak
                    </div>
                </div>
            </div>

            <div fxFlex="70" style="margin-bottom: 40px">


                <p>Kuyruk Sayısı: {{ uploader?.queue?.length }}</p>
                <md-grid-list cols="9" rowHeight="30px">
                    <md-grid-tile colspan="3">Dosya</md-grid-tile>
                    <md-grid-tile></md-grid-tile>
                    <md-grid-tile>Boyut</md-grid-tile>
                    <md-grid-tile>İşlem</md-grid-tile>
                    <md-grid-tile colspan="3">Durum</md-grid-tile>
                    <span *ngFor="let item of uploader.queue">
                        <md-grid-tile colspan="3"> <strong>{{ item?.file?.name }}</strong>  </md-grid-tile>
                        <md-grid-tile> <strong> {{item?.progress}} %</strong>  </md-grid-tile>
                        <md-grid-tile>      {{ (item?.file?.size/1024/1024).toFixed(2) }} MB  </md-grid-tile>
                        <md-grid-tile>
                            <span *ngIf="item.isSuccess"><i class="material-icons " style="color: #0ba048;">check</i></span>
                            <span *ngIf="item.isCancel"><i class="material-icons ">cancel</i></span>
                            <span *ngIf="item.isError"><i class="material-icons">error</i></span>
                        </md-grid-tile>
                        <md-grid-tile>
                            <button type="button" class="btn btn-success btn-xs" style="margin-right: 3px;" (click)="item.upload()" [disabled]="item.isReady || item.isUploading || item.isSuccess">
                                <md-icon>cloud_upload</md-icon><span> Yükle</span>
                            </button>
                        </md-grid-tile>
                        <md-grid-tile>
                            <button type="button" class="btn btn-warning btn-xs" style="margin-right: 3px;" (click)="item.cancel()" [disabled]="!item.isUploading">
                                <md-icon>cancel</md-icon><span> İptal</span>
                            </button>
                        </md-grid-tile>
                        <md-grid-tile>
                            <button type="button" class="btn btn-danger btn-xs" style="margin-right: 3px;" (click)="item.remove()">
                                <md-icon>delete_forever</md-icon><span> Sil </span>
                            </button>
                        </md-grid-tile>
                        <md-grid-tile colspan="9">
                            <md-progress-bar mode="determinate" value="{{item.progress}}"></md-progress-bar>
                        </md-grid-tile>
                    </span>
                    <md-grid-tile colspan="9">
                        Kuyruk işlem:
                    </md-grid-tile>
                    <md-grid-tile colspan="9">
                        <md-progress-bar color="primary" mode="determinate" [value]="uploader.progress" style="height:10px"></md-progress-bar>
                    </md-grid-tile>
                </md-grid-list>
            </div>
        </div>

    </md-card-content>
    <md-card-actions>
        <div style="padding:10px">
            <button (click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length" md-raised-button>Tümünü Yükle</button>
            <button (click)="uploader.cancelAll()" [disabled]="!uploader.isUploading" md-raised-button class="md-raised md-warn">Tümünü İptal Et</button>
            <button (click)="uploader.clearQueue()" [disabled]="!uploader.queue.length" md-raised-button class="md-accent md-hue-1">Liste Temizle</button>
        </div>
        <md-progress-bar color="primary" mode="determinate" [value]="uploader.progress" style="height:10px"></md-progress-bar>
    </md-card-actions>
</md-card>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.