Ion-input type="file" full path

Hello,

I want that my user can choose a file in his browser and then upload that file to firebase.
The filechooser plugin only works on Android.

I try


<ion-item>
      <ion-label id="profile_image" color="primary" stacked>Profilbild wählen</ion-label>
      <ion-input type="file" accept="image/*" id="upload" [(ngModel)]="imageFilePath" (ionChange)="imageFilePath_change($event)"></ion-input>
    </ion-item>

But in my imageFilePath is something like “C:\fakepath\filename.png”.

Google says that this is for security reasons. Is there any way to get the full path in an browser enviroment?

1 Like

What are you planning on using it for?

Upload a user profile image to firebase and show it in the menu as avatar is my target.

You have the file contents, presumably. I assume there is already some sort of name that would be being displayed alongside the avatar. I don’t see why the file path is of any necessity.

IIRC that’s not allowed in Javascript specifically due to security concerns. The new-ish File API implemented in Firefox seems to have a mozFullPath, which looks like what you need. But even if it works, try not to use it (mozilla only and it’s not even documented what it’s for).

I don’t understand this. You have the file contents, no? Isn’t that sufficient?

@rapropos Ahh ok you mean I don’t need the file path.

I changed my Code this way:

HTML

    <ion-item>
      <ion-label id="profile_image" color="primary" stacked>Profilbild wählen</ion-label>
      <ion-input type="file" accept="image/*" (change)="changeListener($event)"></ion-input>
    </ion-item>

TS

 file: File;
 changeListener($event) : void {
    this.file = $event.target.files[0];
  }

  saveProfile_click() {
    console.log("saveProfile_click");
    // Add your code here
    this.afAuth.authState.take(1).subscribe(auth => {
      this.afDatabase.object(`profile/${this.uid}`).set(this.profile)
        .then(() => {
          this.uploadProfileImage();
          this.navCtrl.pop();
        });
    })
  }

  uploadProfileImage(){
    console.log("uploadProfileImage");
    let fileRef = firebase.storage().ref('profileImages/' + this.uid + ".jpg");
    fileRef.put(this.file).then(function(snapshot) {
      console.log('Uploaded a blob or file!');
    });
  }

And it works :slight_smile:

3 Likes

hi there
i hope you would be fine.
it would very kind of you if i can get some guidance from you on this

  <ion-item>
    <ion-label id="profile_image" color="primary" stacked>Profilbild wählen</ion-label>
    <ion-input type="file" accept="image/*" (change)="changeListener($event)"></ion-input>
  </ion-item>
changeListener($event) : void {
     this.file = $event.target.files[0];
     console.log(this.file);
   }

I’m new to ionic. on this code I’m getting the image Data (file). i need the path of the image so i can convert it to Base64 and send it to API

If I remember right, to get the path is not possible for security reasons. The browser wont allow you to interact with the filesystem directly.

I send the file as form data to the server and save it there. Storing the filename in the user profile at my database. I’m also do some stuff like resizing on the server side.

When I need the image in my app I have a route on my server that gets the profile id and send the image as base64 string back to my app.

so how how can i upload it to server throught api

Do input file type work for both ios and android

Yes it works everywhere :slight_smile:

This is my function on the client side. You can extract the important part:


async uploadAvatar(token: string, avatar: File): Promise<Profile> {
    try {
      let formData = new FormData();
      formData.append('avatar', avatar, avatar.name);
      this.userProfile = await this.httpClient.post<Profile>(
        `${this.server}${this.profilesAvatarsRoute}`, 
        formData, 
        {}).toPromise();
      if (this.userProfile.avatar) {
        this.userProfile.avatar = await this.getUserAvatarBase64(token);
      }
      return this.userProfile;
    } catch (err) {
      throw new Error(err.status + " - " + err.statusText);
    }
  }

This is my code on the server side:

app.post('/profiles/avatars', authenticate, uploadProfileAvatar.single('avatar'), function (req, res, next) {
    let fileName = req.user._id.toString() + path.extname(req.file.originalname);
    let filePath = path.join(__dirname, './private/images/avatars/profiles', fileName);
    if (fs.existsSync(filePath)) {
        jimp.read(filePath, function (err, image) {
            if (err) throw err;
            image.resize(256, 256)            // resize
                .quality(60)                 // set JPEG quality
                .write(filePath);            // save
        });
        ...
})

and the middleware

const uploadProfileAvatar = multer({
    storage: profilesStorage,
    fileFilter: function (req, file, callback) {
        var ext = path.extname(file.originalname);
        if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
            return callback(new Error('Only images are allowed'))
        }
        callback(null, true)
    },
    limits: {
        fileSize: 1024 * 1024 * 10 // images up to 10MB
    }
});
1 Like

hey friend, and how get url of image, I think that is downloadURL ?

Well two years is a long time.
But when I get my old code right the image is put as bas64 string in the response.

this.userProfile.avatar = await this.getUserAvatarBase64(token);

The funny thing is that you can use that base 64string in the image tag instead of the url.

But you have to Google that. I forgot how exactly this will work.

I did it this way because I didn’t want to make the url public so it won’t be to easy to download the image from other people.

This is totally up to whoever is writing the backend, and how you would want to go about doing it depends on what your priorities are. Apparently @Jacktoolsnet in this instance is building Data URLs, which work great for very small images, but are a bad choice for anything larger, due to the fact that they waste 33% extra bandwidth. For larger things, what I use are simply UUIDs.

That’s right. But in my case the backend makes the image small. 48X48 pixels or so. And I think I saved it direct in the mongodb.