Ionic 3: WARNING: sanitizing unsafe URL value

13,572

Solution 1

I do not know much about Ionic, but loading an img in Angular could cause an UnsafeUrl Exception.

Maybe you need to use a Dom Sanitizer.

DomSanitizer using example:

Inject it:

constructor(private sanitizer: DomSanitizer,) {}

And use a function to get the img content:

getImgContent(): SafeUrl {
        return this.sanitizer.bypassSecurityTrustUrl(this.imgFile);
    }

So you use in HTML Part:

<img class="object-img"
                   [src]="getImgContent()">

Solution 2

Answering a bit late, but try to add File Path plugin to your project. You can pass your URL and the plugin will resolve it.

Note that this plugin is supported only on Android devices

Share:
13,572

Related videos on Youtube

mm1975
Author by

mm1975

Updated on May 25, 2022

Comments

  • mm1975
    mm1975 almost 2 years

    I´m trying to take a photo and analyze it with the tesseract OCR engine in ionic 3 App for iOS. I´m trying to run it on a iPhone 8 iOS 11.2.6 Unfortunately I get an error in Xcode after taking a photo, and the app crashes:

    NSURLConnection finished with error - code -1002 and also WARNING: sanitizing unsafe URL value assets-library://asset/asset.JPG?id=A791150A-3E89-400E-99D3-E7B3A3D888AA&ext=JPG

    Thank you for your help

    home.html

      <h3 *ngIf="debugText">Debug: {{debugText}}</h3>
        <span>{{recognizedText}}</span>
        <!--<img src="assets/img/demo.png" #demoImg class="start-api" />-->
        <img [src]="image" #imageResult />
    
        <div *ngIf="_ocrIsLoaded && !image">
                <!--<img src="assets/img/Start-arrow.png" #start class="start-arrow" />-->
        </div>
    

    home.ts:

    import { Component, ViewChild, ElementRef, NgZone } from '@angular/core';
    import { NavController } from 'ionic-angular';
    import { Camera } from '@ionic-native/camera';
    import { Platform, ActionSheetController, LoadingController } from 'ionic-angular';
    
    import Tesseract from 'tesseract.js';
    
    @Component({
      selector: 'page-home',
      templateUrl: 'home.html'
    })
    export class HomePage {
      @ViewChild('imageResult') private imageResult: ElementRef;
      @ViewChild('demoImg') private demoImg: ElementRef;
    
      private recognizedText: string;
    
      image: string = '';
      _zone: any;
      _ocrIsLoaded: boolean = false;
    
      brightness: number = 12;
      contrast: number = 52;
      unsharpMask: any = { radius: 100, strength: 2 };
      hue: number = -100;
      saturation: number = -100;
    
      showEditFilters: boolean = false;
    
      debugText: string = '';
    
      constructor(
        private camera: Camera,
        public navCtrl: NavController,
        public platform: Platform,
        public loadingCtrl: LoadingController,
        public actionsheetCtrl: ActionSheetController) {
    
        this._zone = new NgZone({ enableLongStackTrace: false });
      }
    
      openMenu() {
        if (this._ocrIsLoaded === true) {
          let actionSheet;
          if (!this.image) {
            actionSheet = this.actionsheetCtrl.create({
              title: 'Actions',
              cssClass: 'action-sheets-basic-page',
              buttons: [
                {
                  text: 'Random demo',
                  icon: !this.platform.is('ios') ? 'shuffle' : null,
                  handler: () => {
                    this.randomDemo()
                  }
                },
                {
                  text: 'Take Photo',
                  icon: !this.platform.is('ios') ? 'camera' : null,
                  handler: () => {
                    this.takePicture()
                  }
                },
                {
                  text: 'Cancel',
                  role: 'cancel', // will always sort to be on the bottom
                  icon: !this.platform.is('ios') ? 'close' : null,
                  handler: () => {
                    console.log('Cancel clicked');
                  }
                }
              ]
            });
          }
          else {
            actionSheet = this.actionsheetCtrl.create({
              title: 'Actions',
              cssClass: 'action-sheets-basic-page',
              buttons: [
                {
                  text: 'Random demo',
                  icon: !this.platform.is('ios') ? 'shuffle' : null,
                  handler: () => {
                    this.randomDemo()
                  }
                },
                {
                  text: 'Re-Take photo',
                  icon: !this.platform.is('ios') ? 'camera' : null,
                  handler: () => {
                    this.takePicture()
                  }
                },
                {
                  text: 'Apply filters',
                  icon: !this.platform.is('ios') ? 'barcode' : null,
                  handler: () => {
                    this.filter()
                  }
                },
                {
                  text: 'Clean filters',
                  icon: !this.platform.is('ios') ? 'refresh' : null,
                  handler: () => {
                    this.restoreImage()
                  }
                },
                {
                  text: this.showEditFilters == false ? 'Customize filters' : 'Hide customization filters',
                  icon: !this.platform.is('ios') ? 'hammer' : null,
                  handler: () => {
                    this.showEditFilters = this.showEditFilters == false ? true : false;
                  }
                },
                {
                  text: 'Read image',
                  icon: !this.platform.is('ios') ? 'analytics' : null,
                  handler: () => {
                    this.analyze(this.imageResult.nativeElement.src, false);
                  }
                },
                {
                  text: 'Cancel',
                  role: 'cancel', // will always sort to be on the bottom
                  icon: !this.platform.is('ios') ? 'close' : null,
                  handler: () => {
                    console.log('Cancel clicked');
                  }
                }
              ]
            });
          }
          actionSheet.present();
        }
        else {
          alert('OCR API is not loaded');
        }
      }
    
      restoreImage() {
        if (this.image) {
          this.imageResult.nativeElement.src = this.image;
        }
      }
    
      takePicture() {
        let loader = this.loadingCtrl.create({
          content: 'Please wait...'
        });
        loader.present();
    
        // Take a picture saving in device, as jpg and allows edit
        this.camera.getPicture({
          quality: 100,
          destinationType: this.camera.DestinationType.NATIVE_URI,
          encodingType: this.camera.EncodingType.JPEG,
          targetHeight: 1000,
          sourceType: 1,
          allowEdit: true,
          saveToPhotoAlbum: true,
          correctOrientation: true
        }).then((imageURI) => {
          loader.dismissAll();
    
          this.image = imageURI;
          this.debugText = imageURI;
    
        }, (err) => {
          //console.log(`ERROR -> ${JSON.stringify(err)}`);
        });
      }
    
      filter() {
        /// Initialization of glfx.js
        /// is important, to use js memory elements
        /// access to Window element through (<any>window)
        try {
          var canvas = (<any>window).fx.canvas();
        } catch (e) {
          alert(e);
          return;
        }
    
        /// taken from glfx documentation
        var imageElem = this.imageResult.nativeElement; // another trick is acces to DOM element
        var texture = canvas.texture(imageElem);
    
        canvas.draw(texture)
          .hueSaturation(this.hue / 100, this.saturation / 100)//grayscale
          .unsharpMask(this.unsharpMask.radius, this.unsharpMask.strength)
          .brightnessContrast(this.brightness / 100, this.contrast / 100)
          .update();
    
        /// replace image src 
        imageElem.src = canvas.toDataURL('image/png');
      }
    
      analyze(image, loadAPI) {
        let loader = this.loadingCtrl.create({
          content: 'Please wait...'
        });
        loader.present();
    
        if (loadAPI == true) {
          this._ocrIsLoaded = false;
        }
        /// Recognize data from image
        Tesseract.recognize(image, {})
          .progress((progress) => {
            this._zone.run(() => {
              loader.setContent(`${progress.status}: ${Math.floor(progress.progress * 100)}%`)
              console.log('progress:', progress);
            })
          })
          .then((tesseractResult) => {
            this._zone.run(() => {
              loader.dismissAll();
              if (loadAPI == true) {
                this._ocrIsLoaded = true;
              }
              console.log('Tesseract result: ');
              console.log(tesseractResult);
              /// Show a result if data isn't initializtion
              if (loadAPI != true) { this.recognizedText = tesseractResult.text; }
            });
          });
      }
    
      randomDemo() {
    
      }
    
      ionViewDidLoad() {
        console.log('loaded')
        this.analyze(this.demoImg.nativeElement.src, true);
      }
    }
    

    info.plist:

        <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
      <dict>
        <key>CFBundleDevelopmentRegion</key>
        <string>English</string>
        <key>CFBundleDisplayName</key>
        <string>Diagnyzer</string>
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleIcons</key>
        <dict/>
        <key>CFBundleIcons~ipad</key>
        <dict/>
        <key>CFBundleIdentifier</key>
        <string>io.ionic.diagnyzer</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
        <string>0.0.1</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
        <string>0.0.1</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
        <key>NSMainNibFile</key>
        <string/>
        <key>NSMainNibFile~ipad</key>
        <string/>
        <key>UISupportedInterfaceOrientations</key>
        <array>
          <string>UIInterfaceOrientationPortrait</string>
          <string>UIInterfaceOrientationLandscapeLeft</string>
          <string>UIInterfaceOrientationLandscapeRight</string>
        </array>
        <key>UISupportedInterfaceOrientations~ipad</key>
        <array>
          <string>UIInterfaceOrientationPortrait</string>
          <string>UIInterfaceOrientationLandscapeLeft</string>
          <string>UIInterfaceOrientationPortraitUpsideDown</string>
          <string>UIInterfaceOrientationLandscapeRight</string>
        </array>
        <key>UIRequiresFullScreen</key>
        <true/>
        <key>NSAppTransportSecurity</key>
        <dict>
          <key>NSExceptionDomains</key>
          <dict>
            <key>ionic.local</key>
            <dict>
              <key>NSExceptionAllowsInsecureHTTPLoads</key>
              <true/>
            </dict>
          </dict>
          <key>NSAllowsArbitraryLoads</key>
          <true/>
        </dict>
        <key>NSCameraUsageDescription</key>
        <string>This app needs camera access</string>
        <key>NSPhotoLibraryUsageDescription</key>
        <string>This app needs read/write-access photo library access</string>
        <key>NSLocationWhenInUseUsageDescription</key>
        <string/>
        <key>NSMicrophoneUsageDescription</key>
        <string>This app needs microphone access</string>
        <key>NSPhotoLibraryAddUsageDescription</key>
        <string>This app needs write-access to photo library</string>
      </dict>
    </plist>