File Upload Tutorial

Uploading a file in an ASP.NET Zero application is not different than a regular ASP.NET Core & Angular application. In this tutorial, we will implement a file upload functionality in ASP.NET Zero. We will also send an additional field to server while uploading a file.

This tutorial assumes that, you already have a valid ASP.NET Zero license and already created an empty project by following Getting Started document.

First, create a class named FileUploadViewModel in *.Web.Host\Areas\AppAreaName\Models folder. This class will be used to transfer additional parameters during the upload process.

public class FileUploadImageViewModel
{
    public string Description { get; set; }
}

Then, create a controller named FileUploadController in *.Web.Host\Controllers folder. This controller will handle the upload process.

[AbpMvcAuthorize(AppPermissions.Pages_FileUpload)]
public class FileUploadController : AbpZeroTemplateControllerBase
{
    private readonly IHostEnvironment _env;
    public FileUploadController(IHostEnvironment env)
    {
        _env = env;
    }
    
    [HttpPost]
    public async Task<string> UploadFile(FileUploadViewModel model)
    {
       	var image = Request.Form.Files.First();
        var uniqueFileName = GetUniqueFileName(image.FileName);
        var dir = Path.Combine(_env.ContentRootPath, "Images");
        if (!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
        }
        var filePath = Path.Combine(dir, uniqueFileName);
        await image.CopyToAsync(new FileStream(filePath, FileMode.Create));
        SaveImagePathToDb(input.Description, filePath);
        return uniqueFileName;
    }
    
    private string GetUniqueFileName(string fileName)
    {
        fileName = Path.GetFileName(fileName);
        return Path.GetFileNameWithoutExtension(fileName)
               + "_"
               + Guid.NewGuid().ToString().Substring(0, 4)
               + Path.GetExtension(fileName);
    }
    
    private void SaveImagePathToDb(string description, string filepath)
    {
        //todo: description and file path to db
    }
}

The server side of the implementation is done. Let's move to Angular application.

  • Go to angular folder in your project.

  • Open a terminal and run cd src\app\admin.

  • Run ng g component file-upload. That will create a component in admin folder.

  • Go to src\app\shared\layout\nav\app-navigation.service.ts and add new menu item

    new AppMenuItem('FileUpload', 'Pages.FileUpload', 'flaticon-file-1', '/app/admin/fileUpload'),
    
  • Go to src\app\admin\admin-routing.module.ts and add new route for file upload page

    { path: 'fileUpload', component: FileUploadTestComponent },
    
  • Go to generated file-upload.component.html file and change the content as seen below

<div [@routerTransition]>
    <div class="content d-flex flex-column flex-column-fluid">
        <sub-header [title]="'FileUpload' | localize">
        </sub-header>
        <div [class]="containerClass">
            <div class="card card-custom">
                <div class="card-body">
                    <form id="fileUploadForm" enctype="multipart/form-data" #fileUploadForm="ngForm"
                          (ngSubmit)="save()">
                        <div class="form-group">
                            <label for="Description">{{"Description" | localize}}</label>
                            <input class="form-control" type="text" id="Description" name="Description"
                                   [(ngModel)]="description" required>
                        </div>

                        <div class="form-group">
                            <label for="Image">{{"Image" | localize}}</label>
                            <input class="form-control" type="file" id="Image" name="Image" required
                                   (change)="fileChangeEvent($event)">
                        </div>
                        <button type="submit"
                                class="btn btn-light-primary font-weight-bold close-button"
                                [disabled]="!fileUploadForm.form.valid">{{"Upload" | localize}}
                        </button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
  • Go to generated file-upload.component.ts file and change the content as seen below

    import {Component, Injector, OnInit} from '@angular/core';
    import {FileUploader, FileUploaderOptions, FileItem} from 'ng2-file-upload';
    import {AppComponentBase} from "@shared/common/app-component-base";
    import {ProfileServiceProxy} from "@shared/service-proxies/service-proxies";
    import {IAjaxResponse, TokenService} from "@node_modules/abp-ng2-module";
    import {AppConsts} from "@shared/AppConsts";
    import {appModuleAnimation} from "@shared/animations/routerTransition";
    
    @Component({
        templateUrl: './file-upload-test.component.html',
        animations: [appModuleAnimation()]
    })
    export class FileUploadTestComponent extends AppComponentBase implements OnInit {
        public uploader: FileUploader;
        private _uploaderOptions: FileUploaderOptions = {};
        description: string;
    
        constructor(
            injector: Injector,
            private _profileService: ProfileServiceProxy,
            private _tokenService: TokenService
        ) {
            super(injector);
        }
    
        ngOnInit() {
            this.initFileUploader();
        }
    
        initFileUploader(): void {
            this.uploader = new FileUploader({url: AppConsts.remoteServiceBaseUrl + '/FileUpload/UploadFile'});
            this._uploaderOptions.autoUpload = false;
            this._uploaderOptions.authToken = 'Bearer ' + this._tokenService.getToken();
            this._uploaderOptions.removeAfterUpload = true;
            this.uploader.onAfterAddingFile = (file) => {
                file.withCredentials = false;
            };
    
            this.uploader.onBuildItemForm = (fileItem: FileItem, form: any) => {
                form.append('Description', this.description);
            };
    
            this.uploader.onSuccessItem = (item, response, status) => {
                const resp = <IAjaxResponse>JSON.parse(response);
                if (resp.success) {
                    this.message.success(this.l("FileSavedSuccessfully", response.result));
                } else {
                    this.message.error(resp.error.message);
                }
            };
    
            this.uploader.setOptions(this._uploaderOptions);
        }
    
        save(): void {
            this.uploader.uploadAll();
        }
    
        fileChangeEvent(event: any): void {
            this.uploader.clearQueue();
            this.uploader.addToQueue([event.target.files[0]]);
        }
    }
    
  • Then you will have a file upload page as seen below.

    file-upload-tutorial-page-result

In this document