Search code examples
angularcordovaionic-frameworkcordova-pluginsionic4

Why Ionic 4 doesnt support nativeURL file://


I'm trying to get the video properties from my phone storage with import { File } from '@ionic-native/file/ngx'; then its getting an error after im trying to display the nativeURL in the HTML.. Not Allowed to load local resource: file:///storage/emulated/0/..

nativeURL image from File plugins

I have tried to downgrade the webview into @1.2.1 and end up with white screen problem. then I remove the webview into the latest one back.

TS:

import { File } from '@ionic-native/file/ngx';
import { FileTransfer, FileUploadOptions, FileTransferObject } from '@ionic-native/file-transfer/ngx';  
...

constructor(
    ....
  private transfer: FileTransfer, 
  private file: File,
) { }

selectVideo() {
    const options: CameraOptions = {
      mediaType: this.camera.MediaType.VIDEO,
      sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
    }

    this.camera.getPicture(options)
      .then( async (videoUrl) => {
        if (videoUrl) {
          console.log("Here");
          this.uploadedVideo = null;

          var filename = videoUrl.substr(videoUrl.lastIndexOf('/') + 1);
          var dirpath = videoUrl.substr(0, videoUrl.lastIndexOf('/') + 1);
          console.log('dir', dirpath);
          dirpath = dirpath.includes("file://") ? dirpath : "file://" + dirpath;
          //http://localhost/_app_file_/storage/emulated/0/
          // dirpath = this.win.Ionic.WebView.convertFileSrc(dirpath);
          console.log('new dirpath', dirpath);
          try {

            var dirUrl = await this.file.resolveDirectoryUrl(dirpath);
            var retrievedFile = await this.file.getFile(dirUrl, filename, {});
            console.log(dirUrl);
            console.log(retrievedFile);
          } catch(err) {

            console.log("Error Something went wrong.");
          }


          retrievedFile.file( data => {


              // this.dismissLoader();
              if (data.size > MAX_FILE_SIZE) return console.log("You cannot upload more than 5mb.");
              if (data.type !== ALLOWED_MIME_TYPE) return console.log("Incorrect file type.");

              this.selectedVideo = retrievedFile.nativeURL;
          });
        }
      },
      (err) => {
        console.log(err);
      });
  }

HTML:

<div class="video-section" *ngIf="selectedVideo">
  <video controls [src]="selectedVideo"></video>
  <div class="button-options" *ngIf="!uploadedVideo && !isUploading">
    <button ion-button clear (click)="cancelSelection()">
      <ion-icon name="close-circle" color="danger"></ion-icon>
    </button>
    <button ion-button clear (click)="uploadVideo()">
      <ion-icon name="checkmark-circle" color="secondary"></ion-icon>
    </button>
  </div>
  <div *ngIf="isUploading">
    <div class="uploading">
      <p>
        <ion-spinner name="bubbles"></ion-spinner>
      </p>
      <p>Uploading - {{ uploadPercent }}% Complete</p>
    </div>
    <div class="button-options">
      <button ion-button clear (click)="cancelUpload()">
        <ion-icon name="close-circle" color="danger"></ion-icon>
      </button>
    </div>
  </div>
  <div class="button-options" *ngIf="uploadedVideo">
    <button ion-button clear (click)="cancelSelection()">
    Start Over
    </button>
  </div>
</div>

I want to load the video into HTML view. from these properties (nativeURL)


Solution

  • To display the video inside the video HTML element, you need to get the file properties using Cordova plugins.

    Below is working code to get the file in an Android device, and display the read source then render the blob into the DOM. The selected file will be read and put it into a Blob. then you can do whatever you want, like to send it to the API endpoints, or just display the video inside the DOM.

    TS:

    import { Component, ElementRef } from '@angular/core';
    import { FileChooser } from '@ionic-native/file-chooser/ngx';
    import { FilePath } from '@ionic-native/file-path/ngx';
    import { File } from '@ionic-native/file/ngx';
    ...
    
    selectedVideo: any;
    
    constructor(
        private fileChooser: FileChooser,
        private filePath: FilePath,
        private file: File,
        private elementRef: ElementRef,
      ) {
    
    }
    
    getFileData(): Promise<any> {
        return this.fileChooser.open().then(fileURI => {
          return this.filePath.resolveNativePath(fileURI).then(_ => {
            return this.file.resolveLocalFilesystemUrl(fileURI).then((fileEntry: any) => {
              return new Promise((resolve, reject) => {
                fileEntry.file(
                  (file) => {
                    console.log('meta', file);
                    let reader = new FileReader();
                    reader.onload = () => {
                      console.log('Loaded: ', reader.result);
                      const blobFile = new Blob([reader.result], { type: file.type });
                      resolve(
                        blobFile
                      );
                    };
                    reader.onerror = error => {
                      console.log('Error: ', error);
                      reject(
                        error
                      );
                    };
                    reader.onabort = () => {
                      console.log('Aborted');
                    };
                    reader.readAsArrayBuffer(file);
    
                    // this.file.resolveLocalFilesystemUrl(file['localURL']).then((entry: any) => {
                    //   var nativePath = entry.toURL();
                    //   console.log('Native URI: ' + nativePath);
    
                    // });
                  }, error => {
                    console.log(error);              
                  }
                );
              });
            });
          });
        });
    }
    
    async selectAFile() {
        this.getFileData().then(async blobFile => {
          console.log(blobFile);
          this.selectedVideo = true;
          let video = this.elementRef.nativeElement.querySelector("#video");
          video.src = window.URL.createObjectURL(blobFile);
    
        }).catch(error => {
          // Something wrong with getting file infomation
          console.log(error);
          this.selectedVideo = false;
        });
    }
    

    HTML:

    <ion-content>
      <div class="video-selection" padding>
        <p>Please select a video for upload from your gallery</p>
        <ion-button (click)="selectAFile()">Select Video</ion-button>
      </div>
      <video *ngIf="selectedVideo" id="video" controls autoplay></video>
    </ion-content>