Skip to content Skip to sidebar Skip to footer

Angular Firebase Wait for Image to Be Uploaded

Wellness Check

@angular/core@7.3
firebase@5

Firebase makes it easy to upload a huge payload of raw files a cloud storage saucepan. The following lesson will teach you how to upload files to Firebase Storage with Angular, including several advanced concepts almost how to…

  • Handle multiple simultaneous concurrent file uploads.
  • Save the resulting download URL to Firestore.
  • Display a progress bar and provide UI controls to pause, cancel, and resume uploads.
Firebase storage demo with multiple files

This post kickoff appeared as [Episode 82 on AngularFirebase.com](https://angularfirebase.com/lessons/firebase-storage-with-angularfire-dropzone-file-uploader/) and has been updated to handle multiple files and save additional data to Firestore.

The demo video beneath demonstrates how the complete feature should work afterwards completing this lesson.

Footstep 0 - Prerequisites

  1. Install @angular/fire ✔️ How to install @angular/burn, aka AngularFire2

Base CSS Styles

Beneath you will detect the base CSS styles for a basic dropzone.

file_type_scss2 styles.scss

                              .dropzone                {                display                :                flex                ;                align-items                :                center                ;                justify-content                :                center                ;                flex-direction                :                column                ;                min-width                :                80vw                ;                font-weight                :                200                ;                superlative                :                300px                ;                border                :                2px                dashed                #f16624                ;                border-radius                :                5px                ;                background                :                white                ;                margin                :                10px                0                ;                &                .hovering                {                border                :                2px                solid                #f16624                ;                colour                :                #dadada                !                important                ;                }                .file-label                {                font-size                :                one                .2em                ;                }                }                progress                ::-webkit-progress-value                {                transition                :                width                0                .1s                ease                ;                }                          

Footstep ane - Directive to Receive Files from the Browser

Desire to skip this footstep? Consider using this zero-dependency [file-driblet](https://github.com/GoogleChromeLabs/file-drop) web component developed by Google Chrome Labs

The starting time footstep is to create a directive that tin receive the files from the browser. The directive customize the Drag and Drop API to meet the specific needs of our characteristic.

command line

Emit Files as a Custom Event

The most important aspect of the directive below is that it listens to the drib issue on the parent element. This event contains the FileList that the user wants to upload. This data is emitted up as a custom event so it can exist used by our Uploader component in the next step.

In addition, we listen to dragover/dragleave events so we can toggle CSS styles when the user is hovering over the dropzone.

file_type_ng_component_ts dropzone.directive.ts

                              import                {                Directive                ,                HostListener                ,                Output                ,                EventEmitter                }                from                '@angular/core'                ;                @Directive                ({                selector                :                '[dropzone]'                })                export                class                DropzoneDirective                {                @Output                ()                dropped                =                new                EventEmitter                <                FileList                >();                @Output                ()                hovered                =                new                EventEmitter                <                boolean                >();                @HostListener                (                'driblet'                ,                [                '$event'                ])                onDrop                (                $event                )                {                $event                .                preventDefault                ();                this                .                dropped                .                emit                (                $consequence                .                dataTransfer                .                files                );                this                .                hovered                .                emit                (                false                );                }                @HostListener                (                'dragover'                ,                [                '$effect'                ])                onDragOver                (                $event                )                {                $result                .                preventDefault                ();                this                .                hovered                .                emit                (                truthful                );                }                @HostListener                (                'dragleave'                ,                [                '$upshot'                ])                onDragLeave                (                $event                )                {                $result                .                preventDefault                ();                this                .                hovered                .                emit                (                fake                );                }                }                          

Step 2 - Uploader Component

The adjacent footstep is put our directive to use in a component that will receive the files and loop over them. This component does not apply Firebase directly, but rather information technology manages the files dropped by the user and renders an upload-task (which nosotros will build in stride iii) component for each file.

command line

Heed to File Drop

The HTML we add the dropzone directive to a div and heed the custom events that it emits. In improver, we loop over a list of files and render upload-chore which volition be created in the next footstep.

file_type_html uploader.component.html

                              <                div                grade                =                "dropzone"                dropzone                (                hovered                )="                toggleHover                ($                event                )"                (                dropped                )="                onDrop                ($                effect                )"                [                class                .                hovering                ]="                isHovering                "                >                <                h3                >AngularFire Drop Zone</                h3                >                <                p                >Drag and Drop a File</                p                >                </                div                >                <                h3                >Uploads</                h3                >                <                div                *                ngFor                =                "let file of files"                >                <                upload-task                [                file                ]="                file                "                ></                upload-task                >                </                div                >                          

The component typescript is very simple - it only takes the FileList dropped on the div and pushes it to an array.

file_type_ng_component_ts uploader.component.ts

                              import                {                Component                }                from                '@angular/core'                ;                @Component                ({                selector                :                'uploader'                ,                templateUrl                :                './uploader.component.html'                ,                styleUrls                :                [                './uploader.component.scss'                ]                })                export                class                UploaderComponent                {                isHovering:                boolean                ;                files:                File                []                =                [];                toggleHover                (                event:                boolean                )                {                this                .                isHovering                =                event                ;                }                onDrop                (                files:                FileList                )                {                for                (                let                i                =                0                ;                i                <                files                .                length                ;                i                ++                )                {                this                .                files                .                push                (                files                .                particular                (                i                ));                }                }                }                          

Step 3 - Upload Task Component

command line

              ng yard component upload-task            

Each child component is a self contained UploadTask that will outset running every bit presently as the component is initialized. It volition display the upload progress in realtime and save the download URL in firestore when it completes.

There is no hard limit on the number of files you can ship to Firebase simultaneously. The SDK will endeavour to utilize the most efficient strategy bachelor to transfer them to the cloud, which is mostly dependent on the user's network connection.

Show Progress and Provide User Controls

The HTML provides a progress bar and several buttons that let the user to pause, abolish, or resume an private upload.

file_type_html upload-chore.component.html

                              <                div                *                ngIf                =                "percentage | async as pct"                >                <                progress                [                value                ]="                per centum                "                max                =                "100"                ></                progress                >                {{ pct | number }}%                </                div                >                <                div                *                ngIf                =                "snapshot | async as snap"                >                {{ snap.bytesTransferred }} of {{ snap.totalBytes }}                <                div                *                ngIf                =                "downloadURL as url"                >                <                h3                >Results!</                h3                >                <                img                [                src                ]="                url                "                ><                br                >                <                a                [                href                ]="                url                "                target                =                "_blank"                rel                =                "noopener"                >Download Me!</                a                >                </                div                >                <                button                (                click                )="                task                .                pause                ()"                [                disabled                ]="!                isActive                (                snap                )"                >Interruption</                button                >                <                push                (                click                )="                task                .                abolish                ()"                [                disabled                ]="!                isActive                (                snap                )"                >Cancel</                push button                >                <                button                (                click                )="                job                .                resume                ()"                [                disabled                ]="!(                snap                ?.                state                                =                ==                '                paused                ')"                >Resume</                button                >                </                div                >                          

The component is responsible for managing the state of the upload. In this demo, the upload starts transferring data when initialized with ngOnInit. It takes the file as an input belongings, then uses it's name as a reference in the storage bucket. Keep in listen, storage path names must be unique (merely similar whatever filesystem), then we also add a timestamp to the name to ensure uniqueness on each upload.

The snapshotChanges Observable emits data every few hundred milliseconds with information most the upload'due south progress. You lot can use it for progress indicators or alternatively utilise percentageChanges to heed the current progress ranging from 0 to 100.

Nosotros can detect when the upload has finished using the RxJS finalize operator. At this bespeak, we can fetch the public download URL and salvage information technology to Firestore for easy access in the time to come.

Firebase storage uploads with a reference to Firestore

file_type_ng_component_ts upload-task.component.ts

                              import                {                Component                ,                OnInit                ,                Input                ,                ChangeDetectorRef                }                from                '@athwart/core'                ;                import                {                AngularFireStorage                ,                AngularFireUploadTask                }                from                '@angular/burn/storage'                ;                import                {                AngularFirestore                }                from                '@angular/fire/firestore'                ;                import                {                Appreciable                }                from                'rxjs'                ;                import                {                finalize                ,                tap                }                from                'rxjs/operators'                ;                @Component                ({                selector                :                'upload-job'                ,                templateUrl                :                './upload-chore.component.html'                ,                styleUrls                :                [                './upload-chore.component.scss'                ]                })                consign                class                UploadTaskComponent                implements                OnInit                {                @Input                ()                file:                File                ;                task:                AngularFireUploadTask                ;                percentage:                Observable                <                number                >;                snapshot:                Observable                <                any                >;                downloadURL:                string                ;                constructor                (                private                storage:                AngularFireStorage                ,                private                db:                AngularFirestore                )                {                }                ngOnInit() {                this                .                startUpload                ();                }                startUpload() {                // The storage path                                                const                path                =                `exam/                ${                Date                .                now                ()                }                _                ${                this                .                file                .                name                }                `                ;                // Reference to storage saucepan                                                const                ref                =                this                .                storage                .                ref                (                path                );                // The principal job                                                this                .                task                =                this                .                storage                .                upload                (                path                ,                this                .                file                );                // Progress monitoring                                                this                .                per centum                =                this                .                chore                .                percentageChanges                ();                this                .                snapshot                =                this                .                task                .                snapshotChanges                ().                piping                (                tap                (                console                .                log                ),                // The file'southward download URL                                                finalize                (                async                ()                =>                {                this                .                downloadURL                =                await                ref                .                getDownloadURL                ().                toPromise                ();                this                .                db                .                collection                (                'files'                ).                add                (                {                downloadURL:                this.downloadURL                ,                path                });                }),                );                }                isActive                (                snapshot                )                {                return                snapshot                .                state                ===                'running'                &&                snapshot                .                bytesTransferred                <                snapshot                .                totalBytes                ;                }                }                          

The final outcome should await something like this:

smithquichishipt.blogspot.com

Source: https://fireship.io/lessons/angular-firebase-storage-uploads-multi/

Post a Comment for "Angular Firebase Wait for Image to Be Uploaded"