简体   繁体   中英

Aspnetboilerplate Angular File Upload

I am trying to build a file upload with the aspnetboilerplate .net core and angular spa. I am new to the framework and really like it but can't get the file upload working.

First if this can be done in a service without a controller that would be my preferred solution.

Currently I am trying a controller with the code below but it doesn't work

Here is .ts component method to upload file.

   upload(files) {
       if (files.length === 0)
           return;

        const formData = new FormData();

        for (let file of files)
            formData.append(file.name, file);

        const uploadReq = new HttpRequest('POST', `api/FileUpload/UploadFile`, formData, {
            reportProgress: true,
        });

        this.http.request(uploadReq).subscribe(event => {
            if (event.type === HttpEventType.UploadProgress)
                this.progress = Math.round(100 * event.loaded / event.total);
            else if (event.type === HttpEventType.Response)
                this.reqMessage = event.body.toString();
        });
    }

I put the controller in the myapp web host controller folder (The same folder where the antiforgery controller exist)

Here is my controller

[Route("api/[controller]")]
[ApiController]
public class FileUploadController : myappControllerBase
{

    private IHostingEnvironment _hostingEnvironment;

    public FileUploadController(IHostingEnvironment hostingEnvironment)
    {
        _hostingEnvironment = hostingEnvironment;
    }

    [HttpPost, DisableRequestSizeLimit]
    public ActionResult UploadFile()
    {
        try
        {
            var file = Request.Form.Files[0];
            string folderName = "Upload";
            string webRootPath = _hostingEnvironment.WebRootPath;
            string newPath = Path.Combine(webRootPath, folderName);
            if (!Directory.Exists(newPath))
            {
                Directory.CreateDirectory(newPath);
            }
            if (file.Length > 0)
            {
                string fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
                string fullPath = Path.Combine(newPath, fileName);
                using (var stream = new FileStream(fullPath, FileMode.Create))
                {
                    file.CopyTo(stream);
                }
            }
            return Json("Upload Successful.");
        }
        catch (System.Exception ex)
        {
            return Json("Upload Failed: " + ex.Message);
        }
    }

}

Not sure if the formData is setup correct but it does not reach my controller.

Check out the sample code that uploads profile picture...

UploadProfilePicture() controller method:

public class FileUploadController : myappControllerBase
{
      public UploadProfilePictureOutput UploadProfilePicture()
            {
                try
                {
                    var profilePictureFile = Request.Form.Files.First();

                    //Check input
                    if (profilePictureFile == null)
                    {
                        throw new UserFriendlyException("An error occurred!");
                    }

                    if (profilePictureFile.Length > 9999999) //change the max value
                    {
                        throw new UserFriendlyException("Picture exceeds max size!));
                    }

                    byte[] fileBytes;
                    using (var stream = profilePictureFile.OpenReadStream())
                    {
                        fileBytes = stream.GetAllBytes();
                    }

                    //Save new picture
                    var fileInfo = new FileInfo(profilePictureFile.FileName);
                    var tempFileName = Guid.NewGuid().ToString() + fileInfo.Extension;
                    var tempFilePath = Path.Combine(@"c:\temp\upload", tempFileName);
                    System.IO.File.WriteAllBytes(temp1FilePath, fileBytes);

                    using (var bmpImage = new Bitmap(tempFilePath))
                    {
                        return new UploadProfilePictureOutput
                        {
                            FileName = tempFileName,
                            Width = bmpImage.Width,
                            Height = bmpImage.Height
                        };
                    }
                }
                catch (UserFriendlyException ex)
                {
                    return new UploadProfilePictureOutput(new ErrorInfo(ex.Message));
                }
            }
    }
}

UploadProfilePictureOutput.cs:

public class UploadProfilePictureOutput : ErrorInfo
    {
        public string FileName { get; set; }

        public int Width { get; set; }

        public int Height { get; set; }

        public UploadProfilePictureOutput()
        {

        }

        public UploadProfilePictureOutput(ErrorInfo error)
        {
            Code = error.Code;
            Details = error.Details;
            Message = error.Message;
            ValidationErrors = error.ValidationErrors;
        }
}

Angular side:

import { IAjaxResponse } from '@abp/abpHttpInterceptor';
import { TokenService } from '@abp/auth/token.service';
import { Component, Injector, ViewChild } from '@angular/core';
import { AppConsts } from '@shared/AppConsts';
import { AppComponentBase } from '@shared/common/app-component-base';
import { ProfileServiceProxy, UpdateProfilePictureInput } from '@shared/service-proxies/service-proxies';
import { FileUploader, FileUploaderOptions } from 'ng2-file-upload';
import { ModalDirective } from 'ngx-bootstrap';
import { finalize } from 'rxjs/operators';

@Component({
    selector: 'changeProfilePictureModal',
    templateUrl: './change-profile-picture-modal.component.html'
})
export class ChangeProfilePictureModalComponent extends AppComponentBase {

    @ViewChild('changeProfilePictureModal') modal: ModalDirective;

    public active = false;
    public uploader: FileUploader;
    public temporaryPictureUrl: string;
    public saving = false;

    private maxProfilPictureBytesUserFriendlyValue = 5;
    private temporaryPictureFileName: string;
    private _uploaderOptions: FileUploaderOptions = {};

    constructor(
        injector: Injector,
        private _profileService: ProfileServiceProxy,
        private _tokenService: TokenService
    ) {
        super(injector);
    }

    initializeModal(): void {
        this.active = true;
        this.temporaryPictureUrl = '';
        this.temporaryPictureFileName = '';
        this.initFileUploader();
    }

    show(): void {
        this.initializeModal();
        this.modal.show();
    }

    close(): void {
        this.active = false;
        this.imageChangedEvent = '';
        this.uploader.clearQueue();
        this.modal.hide();
    }

    imageChangedEvent: any = '';

    fileChangeEvent(event: any): void {
        this.imageChangedEvent = event;
    }

    imageCroppedFile(file: File) {
        var files: File[] = [file];
        this.uploader.clearQueue();
        this.uploader.addToQueue(files);
    }

    initFileUploader(): void {
        this.uploader = new FileUploader({ url: "http://localhost:22742/Profile/UploadProfilePicture' });
        this._uploaderOptions.autoUpload = false;
        this._uploaderOptions.authToken = 'Bearer ' + this._tokenService.getToken();
        this._uploaderOptions.removeAfterUpload = true;
        this.uploader.onAfterAddingFile = (file) => {
            file.withCredentials = false;
        };

        this.uploader.onSuccessItem = (item, response, status) => {
            const resp = <IAjaxResponse>JSON.parse(response);
            if (resp.success) {
                this.updateProfilePicture(resp.result.fileName);
            } else {
                this.message.error(resp.error.message);
            }
        };

        this.uploader.setOptions(this._uploaderOptions);
    }

    updateProfilePicture(fileName: string): void {
        const input = new UpdateProfilePictureInput();
        input.fileName = fileName;
        input.x = 0;
        input.y = 0;
        input.width = 0;
        input.height = 0;

        this.saving = true;
        this._profileService.updateProfilePicture(input)
            .pipe(finalize(() => { this.saving = false; }))
            .subscribe(() => {
                abp.event.trigger('profilePictureChanged');
                this.close();
            });
    }

    save(): void {
        this.uploader.uploadAll();
    }
}

Note: Don't forget to add bearer token to your ajax upload. Beside, you need to grant write permission to the physical upload directory in your IIS on production.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM