Base solution for your next web application
Open Closed

Angular upload Image #10116


User avatar
0
rvanwoezik created

ASP.NET CORE & Angular (single solution) .NET 5.0 v10.2.0

I have an entity named Course, Course has an Image I copied the functionality from change-profile-picture

Here is my change-course-image-modal.ts

import { IAjaxResponse, TokenService} from 'abp-ng2-module';
import { Component, Injector, ViewChild } from '@angular/core';
import { AppConsts } from '@shared/AppConsts';
import { AppComponentBase } from '@shared/common/app-component-base';
import { CourseServiceProxy, UpdateCourseImageInput } from '@shared/service-proxies/service-proxies';
import { FileUploader, FileUploaderOptions, FileItem } from 'ng2-file-upload';
import { ModalDirective } from 'ngx-bootstrap/modal';
import { finalize } from 'rxjs/operators';
import {ImageCroppedEvent, base64ToFile} from 'ngx-image-cropper';

@Component({
    selector: 'changeCourseImageModal',
    templateUrl: './change-course-image-modal.component.html'
})
export class ChangeCourseImageModalComponent extends AppComponentBase {

    @ViewChild('changeCourseImageModal', {static: true}) modal: ModalDirective;



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

    public maxCourseImageBytesUserFriendlyValue = 5;
    private temporaryPictureFileName: string;
    private _uploaderOptions: FileUploaderOptions = {};

    imageChangedEvent: any = '';

    constructor(
        injector: Injector,
        private _courseService: CourseServiceProxy,
        private _tokenService: TokenService
    ) {
        super(injector);
    }

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

    show(courseId?: number): void {
        this.initializeModal(courseId);
        this.modal.show();

    }

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

    fileChangeEvent(event: any): void {
        if (event.target.files[0].size > 5242880) { //5MB
            this.message.warn(this.l('CourseImage_Warn_SizeLimit', this.maxCourseImageBytesUserFriendlyValue));
            return;
        }

        this.imageChangedEvent = event;
    }

    imageCroppedFile(event: ImageCroppedEvent) {
        this.uploader.clearQueue();
        this.uploader.addToQueue([<File>base64ToFile(event.base64)]);
    }

    initFileUploader(): void {
        this.uploader = new FileUploader({ url: AppConsts.remoteServiceBaseUrl + '/Course/UploadCourseImage' });
        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('FileType', fileItem.file.type);
            form.append('FileName', 'CourseImage');
            form.append('FileToken', this.guid());
            form.append('CourseId', this.courseId);
        };

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

        this.uploader.setOptions(this._uploaderOptions);

    }

    updateCourseImage(fileToken: string): void {
        const input = new UpdateCourseImageInput();
        input.fileToken = fileToken;
        input.x = 0;
        input.y = 0;
        input.width = 0;
        input.height = 0;
        input.courseId = this.courseId;

        this.saving = true;
        this._courseService.updateCourseImage(input)
            .pipe(finalize(() => { this.saving = false; }))
            .subscribe(() => {
                abp.event.trigger('courseImageChanged');
                this.close();
            });
    }
    guid(): string {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        }
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
    }

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

And here is my change-course-modal.html

<div appBsModal #changeCourseImageModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" 
aria-labelledby="myLargeModalLabel" aria-hidden="true" [config]="{backdrop: 'static'}">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <form *ngIf="active" #changeCourseImageModalForm="ngForm" (ngSubmit)="save()">
                <div class="modal-header">
                    <h5 class="modal-title">
                        <span>{{"ChangeProductPicture" | localize}}</span>
                    </h5>
                    <button type="button" class="close" [attr.aria-label]="l('Close')" (click)="close()">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <div class="form-group">
                        <input type="file" (change)="fileChangeEvent($event)" />
                        <span class="help-block m-b-none">{{"CourseImage_Change_Info" | localize:maxCourseImageBytesUserFriendlyValue}}</span>
                    </div>
                    <image-cropper
                        [imageChangedEvent]="imageChangedEvent"
                        [maintainAspectRatio]="true"
                        [aspectRatio]="4 / 4"
                        [resizeToWidth]="128"
                        format="png"
                        (imageCroppedFile)="imageCroppedFile($event)"
                    ></image-cropper>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" (click)="close()" [disabled]="saving">{{"Cancel" | localize}}</button>
                    <button type="submit" class="btn btn-primary" [disabled]="!changeCourseImageModalForm.form.valid || saving"><i class="fa fa-save"></i> <span>{{"Save" | localize}}</span></button>
                </div>
            </form>
        </div>
    </div>
</div>

Problem is that when pressing save on the modal after image resize nothing happens,

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

This gets fired but it doesn't do anyting, i'm not getting any errors. Banging my head on the keyboard several times but without result.

Please advice


3 Answer(s)
  • User Avatar
    0
    ashjackson created

    I've tried this approach too, but had the same issue too, I had assumed I'd not understood correctly the process and parked this for later investigation, so I would be interested to see the "correct" way to upload images in this way is.

    AJ.

  • User Avatar
    0
    rvanwoezik created

    Found it! So stupid

    <image-cropper
                            [imageChangedEvent]="imageChangedEvent"
                            [maintainAspectRatio]="true"
                            [aspectRatio]="4 / 4"
                            [resizeToWidth]="128"
                            format="png"
                            (imageCroppedFile)="imageCroppedFile($event)"
                        ></image-cropper>
    

    (imageCroppedFile)="imageCroppedFile($event)" should be (imageCropped)="imageCroppedFile($event)"

  • User Avatar
    0
    ismcagdas created
    Support Team

    Thank you for sharing the solution @rvanwoezik. Sorry that I haven't seen your question at first.