Pulling remote images and trans.json files

Ok so first i will preface with that i need to do:
1.My app needs to be able to pull an image store it locally and then use that asset in the app. The image will be different for each user but i need it stored locally so i will display even if the app is run offline. For reference this is a profile image.
2.We need translations in the app and i have that working, but we will be adding more translations over time so we want to download those json files when they are online. Translations are working in the app but they pull from assets/i18n/**.json I’d like to be able to download files and store them there.

So after a bunch of troubleshooting i was able to get files to download but i can’t seem to wrote to the assets directory
this fails:

this.fileTransfer.download("https://d30y9cdsu7xlg0.cloudfront.net/png/2048-200.png", this.file.applicationDirectory + "www/assets/2048-200.png").then((data) => {console.log(data);}, (error)=>{console.error(error);});

Could not create target file :"file:///var/containers/Bundle/Application/CD0FE1E6-B272-4DE0-AB11-4D34DCB604EF/MyApp.app/www/assets/generic_tnj_ad.jpg

I know the path is correct since

    this.file.listDir(this.file.applicationDirectory, "www/assets/").then((data)=>{
      console.log(data)
    });

returns a list of the files/directories in the path.
There has to be something to write to that location or to a location where the app can access the files. I tried to download the files to the data directory and the file downloads properly

this.fileTransfer.download(url, this.file.dataDirectory + 'generic_tnj_ad.jpg')

However if i try to use the image in my template it can’t load the local resourc
Template:

  <ion-content style="text-align:center" scroll="false">
    <form (ngSubmit)="login()">
      <img src="{{ headingImage }}" style="padding-top:50px">

the code to get the image path

      this.headingImage = this.file.dataDirectory + 'generic_tnj_ad.jpg';
      console.log(this.headingImage);
    });

that code is even being run after the a reload so the file is already there.
What am i missing about uploading to assest, and what am i missing to reference files from a non assests folder?

This is never going to work as described. The assets folder is a fiction that is mapped to stuff inside your app binary.

If i can’t store the files in the app like that how can reference files that have been downloaded to another writeable path. I just get not allowed to load local resource. Interestingly if i run it in standalone and not livereload it will access the file properly. Do i need to use some other form of the path so that the files can be read from a live-reload version?

If i can’t write to the assets folder how do things like the in-app updater work. it can bypass the approval processes by changing the content in the www folder.

Hi

you will need to use native plugin File to write files to the device.

Regards

Tom

Ok i got it so that it will load my locally stored images in both livereload and standard for anyone who needs to do this you can do so by


import { DomSanitizer } from '@angular/platform-browser';

....

constructor( public navCtrl: NavController, public nativeStorage: NativeStorage, private platform: Platform, public sanitizer: DomSanitizer) {  

....

      this.headingImage = this.file.dataDirectory + "generic_tnj_ad.png";
      file.resolveLocalFilesystemUrl(this.headingImage).then((entry)=>{
        this.headingImage = sanitizer.bypassSecurityTrustResourceUrl(entry.toInternalURL());
      })

...
    this.fileTransfer.download("https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", this.file.dataDirectory + "generic_tnj_ad.png").then((data) => {console.log(data);}, (error)=>{console.error(error);});    

then in the template:

      <img [src]="headingImage" style="padding-top:50px">

Now i just have to figure out how to get the ngtranslate to load locally stored files. I hope that helps someone. the sanitized cdv path was the key

Hi

As far as I can tell, the ionic prescribed way to localize has a pipe that does local http to retrieve data when switching language.

For your files I’d think you may want to write your own pipe class overriding the method to select a new language.

Rgdz

Tom

Ok so i made a lot of progress (I think) and it only took like 5 hours, but now i’m once again stumped. At this point i’m stuck in ng2-tranlate changes.

I can create a loader and get it to load file data from dataDirectory, but somehow i’m not handling the return from the custom TranslateLoader.
The custom translateloader appears to be loading the file but not actually switching/loading the languages.
here is my custom loader

export class CustomTranslationLoader implements TranslateLoader {
	file;
	filename;
	getTranslation(lang: string): Observable<any>{
		this.file = new File();    
		this.filename = this.file.dataDirectory + "japanese.json";

		return Observable.fromPromise(this.file.readAsText(this.file.dataDirectory, 'japanese.json'));
      }
}

seems simple enought if i instead return the following it works

		return Observable.of({"IPC ID or Username": "IPC ID or Username JP", Password: "Password JP", LOGIN: "Login JP", "Remember Me": "Remember Me JP"});

now if i add console.logs into the ng2-translate to see if the file is loaded it returns the data from the file (exactly the same as the json object above. this is from the translate.service.js

    /**
     * Gets an object of translations for a given language with the current loader
     * @param lang
     * @returns {Observable<*>}
     */
    TranslateService.prototype.getTranslation = function (lang) {
        var _this = this;
        this.pending = this.currentLoader.getTranslation(lang).share();
        this.pending.take(1)
            .subscribe(function (res) {
              //both loaders return the same res content.  
              console.log(res);
            _this.translations[lang] = res;
            _this.updateLangs();
            _this.pending = undefined;
        }, function (err) {
            _this.pending = undefined;
        });
        return this.pending;
    };

according to the documentation on the ng2-translate site a custom loader only needs to implement the getTranslation function.
https://github.com/ngx-translate/core/blob/fb02ca5920aae405048ebab50e09db67d5bf12a2/README.md#write--use-your-own-loader

I’m going to keep hacking away at this but i’m at the ends of my whits. Someone please help me out

Found a little more. it appears that the Observable.fromPromise returns a “PromiseObservable” where as the other “Observable.of” returns a StringObservable. The first doesn’t have a value object containing the json values the second does. in stead the 2nd returns a PromiseObservable with a promise object.
I’m guessing getting the first to returns an array of strings like the second will resolve my issue. How to do this however is a big mystery.

I’m just spitballing here, but in your first example it will return a string:
return Observable.fromPromise(this.file.readAsText(this.file.dataDirectory, 'japanese.json'));

While in your second example it will presumably be a JSON object:
return Observable.of({"IPC ID or Username": "IPC ID or Username JP", Password: "Password JP", LOGIN: "Login JP", "Remember Me": "Remember Me JP"});

So I would try doing
return Observable.fromPromise(this.file.readAsText(this.file.dataDirectory, 'japanese.json').then(data => JSON.parse(data)));

Not sure if this will change anything as I’m unsure what ng2-translate is expecting, but you know.

Thank you. while it wasn’t the solution it did reveal a problem with my json in the file. malformed json was causing all my recent pain. i didn’t need to call JSON.parse, just return the string. I just need to make sure the json file is valid json. Thanks again. I can finally finish all of this. I can’t believe that i wasted so much time while i had the code just just f’ed up the data.

I take that back i did have to use the JSON.parse