Loading image with angular2 into asp.net core

So I have a main asp.net application with angular2. Now I want to load an image and I succeeded if I load it as byte []. But then I can't check if the file is really a real image in the backend, so I tried to find other solutions. I found this blog about file uploading: https://devblog.dymel.pl/2016/09/02/upload-file-image-angular2-aspnetcore/ but that doesn't work for me ...

I am using angular2 library angular2-image-upload for file upload, so my image upload part looks like this:

<image-upload [max]="1" [buttonCaption]="'Browse'" [preview]="false" (change)="onFileChange($event)"></image-upload>
<button (click)="onSaveChanges()" class="btn btn-primary float-left" type="submit">Save</button>

      

then my angular2 part looks like this:

onFileChange(event: any) {
    this.file = event.target.files[0];

    if (event.target.files && this.file) {
        var reader = new FileReader();

        reader.onload = (event: any) => {
            this.profilePicture = event.target.result;
        }
        reader.readAsDataURL(this.file);
    }
}

onSaveChanges() {
    this.isSaving = true;
    this.country = this.state.user.country;
    this.userService.userChange(this.firstName, this.lastName, this.country, this.file, this.currentPassword, this.newPassword).subscribe(success => {
        this.state.user.profilePicture = this.profilePicture;
        this.state.user.firstName = this.firstName;
        this.state.user.lastName = this.lastName;
        this.isSaving = false;
        this.passwordError = false;
        this.isSuccessful = true;
        this.currentPassword = '';
        this.newPassword = '';
        this.newPasswordRepeat = '';
    }, error => {
        this.isSaving = false;
        this.passwordError = true;
        this.passwordErrorMessage = error._body;
    });
}

      

my angular2 api call looks like this:

userChange(firstName: string, lastName: string, country: string, file: File, oldPassword: string, newPassword: string) {
    let input = new FormData();
    input.append("File", file);

    var url = this.baseUrl + "updateUser";

    return this.http.post(url, { FirstName: firstName, LastName: lastName, Country: country, File: input, OldPassword: oldPassword, NewPassword: newPassword });
}

      

my main asp.net controller ( NOTE that I am not showing the controller body because it doesn't matter ):

[HttpPost]
public async Task<IActionResult> UpdateUser([FromBody]UserChange userChange)
{ 
}

      

UserChange class:

public class UserChange
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Country { get; set; }

    public IFormFile File { get; set; }

    public string OldPassword { get; set; }

    public string NewPassword { get; set; }
}

      

The thing is, when I post my image, I always get my UserChange object as null. When I added the image as byte [] it worked like a charm , what is the problem? Why am I always getting null even if I am transferring a file that is not null? Another thing that I saw is that when I change the type from IFormFile to FormFile, my UserChange object is no longer empty, but only the File parameter from the object throws this error

'userChange.File.ContentDisposition' threw an exception of type 'System.NullReferenceException'

UPDATE 1

Somehow I managed to send a file to an asp.net controller using this answer: Uploading a file using an Asp.Net Core API file is always null, but for that I had to create another action that has no parameters, but how send the file to my situation is still unknown ...

+3


source to share


1 answer


I found your post when I was looking for something similar and also started by using the angular2-image-upload upload library but decided to try the simple approach first. For my purposes, I only needed a byte [] image file (will try to add form fields for the image title and title below), and found some of what Michael Daimel suggests on his blog here to be very helpful and get it working. Even though you couldn't get your approach to work it helped me a lot.

At the time I was unstuck the correct routing was set up and for a while my file seemed to be loaded correctly into the angular service but was empty when it got to the Load controller. Once I verified that the path from the upload service and the path defined in the controller's [Route ("/ api / upload")] attribute were the same, it all fell into place and I was able to upload successfully. Slightly different from what you had, but this worked for me:

My component load components:

addFile(): void {
    let fi = this.fileInput.nativeElement;
    if (fi.files && fi.files[0]) {
        let fileToUpload = fi.files[0];

        if (fileToUpload) {
            this.uploadService.upload(fileToUpload)
            .subscribe(res => {
                console.log(res);
            });
        }
        else
            console.log("FileToUpload was null or undefined.");
    }
}

      

Boot service call:



upload(fileToUpload: any) {
        let input = new FormData();
        input.append("fileForController", fileToUpload);
        return this.http.post("/api/upload", input );
    }

      

What are the entries in the "Upload" ActionResult of my ImagesController, which looks like this (I am storing my image in the database, so the "path" variable is actually redundant). The 'Image' object is just a simple model for the Url, Title, ImageFileContent and Caption fields:

[HttpPost]
[Route("/api/upload")]
public async Task<IActionResult> Upload(IFormFile fileForController)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    if (fileForController == null) throw new Exception("File is null");
    if (fileForController.Length == 0) throw new Exception("File is empty");

    var theImage = new Image();
    var path = Path.Combine("~\\ClientApp\\app\\assets\\images\\", fileForController.FileName);

    theImage.Url = path + fileForController.FileName;
    theImage.Title = fileForController.Name + "_" + fileForController.FileName;
    theImage.Caption = fileForController.Name + " and then a Surprice Caption";

    using (Stream stream = fileForController.OpenReadStream())
    {
        using (var reader = new BinaryReader(stream))
        {
            var fileContent = reader.ReadBytes((int)fileForController.Length);

            theImage.ImageFileContent = fileContent;
            _context.Images.Add(theImage);

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
    }
    return Ok(theImage);
}

      

And my html template fields were pretty much the same as in Michael Diemel's post:

<form action="gallery" name="fileUploadForm" method="post" enctype="multipart/form-data">
    <div class="col-md-6">
        <input #fileInput type="file" title="Choose Image to upload" />
        <button (click)="addFile()" class="btn btn-success">Add</button>
    </div>
</form>

      

0


source







All Articles