Ionic Native Camera Ios Images Upload to Server

In an older blog post, I wrote virtually uploading pictures from a Cordova app to a Leap Boot server.

With the release of Ionic Capacitor one.0 just a few days agone (May 22, 2019) it's time to revisit this topic and write an upload example with a Capacitor app.

Capacitor is Ionic's solution to wrap applications written in JavaScript, CSS, and HTML into a native container for the iOS and Android platforms. Capacitor works very similarly to Cordova, and the native container exposes the capabilities of the device to the JavaScript application.

There are a few differences to Cordova. A big difference is that Cordova recreates the build binder for Android and iOS each time it builds a new app version. Whereas with Capacitor, you lot create the build folder for Android and iOS in one case and also commit it into the source lawmaking management organization. During development, you then only copy the build output of your JavaScript application into the native app folders (with npx cap re-create or npx cap sync)

Another departure is that the core platform of Capacitor already provides oft used plugins without installing any additional library. You find a list of the plugins that are part of the core here:
https://capacitorjs.com/docs/apis

Capacitor not only supports their own plugins it also supports most of the Cordova plugins, and so you have access to a wide variety of plugins that should work on Capacitor.

Read more about Capacitor on the official homepage:
https://capacitorjs.com/

In this weblog mail service, nosotros are going to create a trivial app where the user can take a photo, and the application automatically uploads it over HTTP to a Spring Kick backend. The app implements the upload in two unlike means. One is using a "normal" upload with Angular's HttpClient, and the other upload uses the JavaScript tus library, that splits the file into multiple chunks and uploads them one by one.

I cover the tus functionality simply briefly in this web log post considering I wrote a blog post about tus that covers this topic in particular: https://golb.hplar.ch/2019/06/upload-with-tus.html

Here a screenshot of the app. With the toggle, y'all can switch between the "normal" and tus.io upload.

app screenshot

Client

Setup

The JavaScript client application is based on the blank Ionic template. Offset, add the JavaScript tus library.

          npm install tus-js-customer                  

and the Capacitor library and CLI

          npm install @capacitor/core npm install -D @capacitor/cli                  

Initialize Capacitor

          npx cap init                  

To employ the Photographic camera plugin, we need to import the Plugins object of @capacitor/core in TypeScript.

                      import            {Plugins,            ...            .            }            from            '@capacitor/core'            ;                  

We can then access the Photographic camera API via the Plugins object: Plugins.Photographic camera.


Camera API

The app presents ii buttons, one to take a photo from the photographic camera and 1 to select a picture from the image gallery. The code backside these buttons is very like. The simply deviation is the source property that we pass in the configuration object to the Photographic camera.getPhoto() method

                      async            takePhoto            (            )            :            Promise            <            void            >            {            const            ab            =            await            this            .            getPhoto            (CameraSource.Camera)            ;            if            (ab)            {            if            (            this            .tus)            {            await            this            .            uploadTus            (ab)            ;            }            else            {            await            this            .            uploadAll            (ab)            ;            }            }            }            async            selectPhoto            (            )            :            Hope            <            void            >            {            const            ab            =            await            this            .            getPhoto            (CameraSource.Photos)            ;            if            (ab)            {            if            (            this            .tus)            {            await            this            .            uploadTus            (ab)            ;            }            else            {            wait            this            .            uploadAll            (ab)            ;            }            }            }            private            async            getPhoto            (source:            CameraSource)            :            Promise            <            string            |            undefined            >            {            const            image            =            wait            Camera.            getPhoto            (            {            quality:            90            ,            allowEditing:            imitation            ,            resultType:            CameraResultType.Uri,            source            }            )            ;            if            (image.webPath)            {            this            .photo            =            this            .sanitizer.            bypassSecurityTrustResourceUrl            (paradigm.webPath)            ;            }            return            image.webPath;            }                  

home.folio.ts

The Camera.getPhoto() method currently only returns jpeg images, and with the quality configuration, nosotros signal the quality of the picture (0 = worst, 100 = best). Greater numbers hateful bigger file sizes.

There are currently three supported returnType: CameraResultType.Base64, CameraResultType.DataUrl and CameraResultType.Uri

The result type Uri returns a path that can be used to prepare the src aspect of an image for efficient loading and rendering. Nosotros run the path commencement through Angular's DomSanitizer to prevent whatsoever XSS issues before nosotros assign it to the variable photo.

This variable is used equally the value for the src attribute in an img tag

                                                    <img              *ngIf                              =                "photo"                            [src]                              =                "photo"                            />                              

habitation.folio.html

See the documentation folio for more information nigh the Camera API:
https://capacitorjs.com/docs/apis/camera


normal upload

The uploadAll() method implements a unproblematic upload with Angular'southward HttpClient. Beginning, nosotros need to catechumen the web path nosotros get from the Camera plugin into a Blob. A straightforward solution is to utilise the Fetch API and "fetch" the spider web path, which returns the desired blob object.

Next, nosotros create a FormData object and suspend a new value with the blob object. The of import thing here is that the proper noun file needs to match the name of the asking parameter on the server we are going to implement in the next section.

                      private            async            uploadAll            (webPath:            cord            )            :            Promise            <            void            >            {            this            .loading            =            await            this            .loadingCtrl.            create            (            {            message:            'Uploading...'            }            )            ;            await            this            .loading.            present            (            )            ;            const            blob            =            await            fetch            (webPath)            .            so            (r            =>            r.            hulk            (            )            )            ;            const            formData            =            new            FormData            (            )            ;            formData.            append            (            'file'            ,            blob,                          `              file-                              ${                this                .counter++                }                            .jpg              `                        )            ;            this            .http.                          mail                              <                boolean                >                                      (                          `                              ${environs.serverUrl}                            /uploadAll              `                        ,            formData)            .            pipe            (            catchError            (east            =>            this            .            handleError            (e)            )            ,            finalize            (            (            )            =>            this            .loading?.            dismiss            (            )            )            )            .            subscribe            (ok            =>            this            .            showToast            (ok)            )            ;            }                  

dwelling house.page.ts

Lastly, nosotros send the file with a regular POST request to the Jump Kicking dorsum end.


tus.io upload

The upload with the JavaScript tus library works very similarly. We also outset need to catechumen the web path into a blob object and so pass this blob to Upload. I won't go much further into detail about tus.io because the code is essentially the aforementioned equally the lawmaking in my web log postal service most tus.io.

                      private            async            uploadTus            (webPath:            string            )            :            Hope            <            void            >            {            this            .loading            =            expect            this            .loadingCtrl.            create            (            {            message:            'Uploading...'            }            )            ;            await            this            .loading.            present            (            )            ;            const            blob            =            look            fetch            (webPath)            .            then            (r            =>            r.            blob            (            )            )            ;            const            upload            =            new            Upload            (blob,            {            endpoint:                          `                              ${environs.serverUrl}                            /upload              `                        ,            retryDelays:            [            0            ,            3000            ,            6000            ,            12000            ,            24000            ]            ,            chunkSize:            512            *            1024            ,            metadata:            {            filename:                          `              file-                              ${                this                .counter++                }                            .jpg              `                        }            ,            onError            :            (            )            =>            {            this            .            showToast            (            false            )            ;            this            .loading?.            dismiss            (            )            ;            }            ,            onSuccess            :            (            )            =>            {            this            .            showToast            (            true            )            ;            this            .loading?.            dismiss            (            )            ;            }            }            )            ;            upload.            start            (            )            ;            }                  

abode.page.ts


Build

With the programme now finished, we can build the project and add together iOS and Android back up.

First, make sure that all required dependencies are installed on your computer:
https://capacitorjs.com/docs/getting-started/dependencies

          ng build --configuration production npx cap add together android npx cap add ios                  

Next, open Android Studio and/or Xcode.

          npx cap run android npx cap run ios                  

From in that location you lot can build the native apps and deploy them to a real device or run them inside an emulator.

Server

The server is a Jump Kick awarding including the Spider web dependency (spring-kicking-starter-web) and is essentially a re-create of the application that I wrote for my previous weblog mail almost tus.io.

I add together one additional HTTP endpoint that handles the "normal" upload request. The important part here is that the request parameter proper noun matches the name in the FormData of the JavaScript client (file).

                      @CrossOrigin            @PostMapping            (            "/uploadAll"            )            @ResponseBody            public            boolean            uploadAll            (            @RequestParam            (            "file"            )            MultipartFile            file)            {            try            {            Path            downloadedFile            =            this            .uploadDirectory            .            resolve            (            Paths            .            go            (file.            getOriginalFilename            (            )            )            )            ;            Files            .            deleteIfExists            (downloadedFile)            ;            Files            .            copy            (file.            getInputStream            (            )            ,            downloadedFile)            ;            render            true            ;            }            catch            (            IOException            due east)            {            LoggerFactory            .            getLogger            (            this            .            getClass            (            )            )            .            fault            (            "uploadAll"            ,            eastward)            ;            return            false            ;            }            }                  

UploadController.coffee

The handling of the file is very straightforward. The lawmaking extracts the bytes with the InputStream from the MultipartFile and writes them into a file in the upload directory.

This likewise supports sending multiple files in one request. On the customer you add multiple blobs the FormData object. Each with a different name.

                      const            formData            =            new            FormData            (            )            ;            formData.            append            (            'file1'            ,            blob1,                          `              file-1.jpg              `                        )            ;            formData.            suspend            (            'file2'            ,            blob2,                          `              file-2.jpg              `                        )            ;                  

and on the HTTP endpoint you define multiple parameters matching the FormData values.

                      public            boolean            uploadAll            (            @RequestParam            (            "file1"            )            MultipartFile            file1,            @RequestParam            (            "file2"            )            MultipartFile            file2)            {                  

And finally, as always, when y'all write a Spring Boot awarding that supports file uploads, cheque and suit the max size settings.

                      spring.servlet.multipart.max-file-size            =            20MB            spring.servlet.multipart.max-asking-size            =            20MB                  

application.properties

The defaults are 1MB for max-file-size and 10MB for max-request-size.

For testing, I utilise ngrok. I get-go the Spring Boot application on my development car, so create a tunnel with ngrok

          ngrok http 8080                  

And ready the path that ngrok gives me in the customer awarding environment file.

                      consign            const            environment            =            {            production:            true            ,            serverUrl:            'https://a946be920a04.ngrok.io'            }            ;                  

environs.prod.ts

Then build the JavaScript awarding, run npx cap copy and build the native app in Xcode and/or Android Studio and deploy it to a real device or emulator.

Web

The nice affair about the Capacitor Camera plugin is that information technology also works on the spider web. Not out of the box, but with minimal changes to the existing code.

First, we add together one additional bundle

          npm install @ionic/pwa-elements                  

so nosotros open src/master.ts and add lawmaking that calls defineCustomElements afterward the Angular app has been loaded.

                      platformBrowserDynamic            (            )            .            bootstrapModule            (AppModule)            .            then            (            (            )            =>            defineCustomElements            (window)            )            .            catch            (err            =>            console            .            error            (err)            )            ;                  

primary.ts

The @ionic/pwa-elements package implements web-based functionality and user interfaces for some Capacitor plugins. This packet will be ignored when you run the application on a device wrapped in Capacitor, but when yous run this in a browser, you get a nice camera user interface.

For more than information about Capacitor visit the official homepage:
https://capacitorjs.com/

As well, read this guide virtually writing a Camera app:
https://capacitorjs.com/docs/guides/ionic-framework-app

Yous detect the source code for the example presented in this weblog mail on GitHub:
https://github.com/ralscha/blog2019/tree/master/capupload

daviscusuneve.blogspot.com

Source: https://golb.hplar.ch/2019/06/uploading-capacitor-spring-boot.html

0 Response to "Ionic Native Camera Ios Images Upload to Server"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel