terikon / cordova-plugin-photo-library

Maintainer needed. Please contact if you're using this library in your project
MIT License
149 stars 295 forks source link

Getting native file location #60

Open AndreasGassmann opened 7 years ago

AndreasGassmann commented 7 years ago

I would like to implement a multi-image uploader in ionic. Currently (single picture upload) I'm using https://github.com/apache/cordova-plugin-file and https://github.com/apache/cordova-plugin-file-transfer to do the upload. It looks like with this library I would have to convert the pictures to base64, which I would like to avoid.

Is there any way to get the native location / resource URI of the pictures with this plugin?

viskin commented 7 years ago

What will be the data flow in your project? Is it like this:

viskin commented 7 years ago

It's possible to add native path for Android, it event existed in the past. Was removed because it didn't work in iOS, and I want this library to have equal capabilities in both platforms.

AndreasGassmann commented 7 years ago

Yes, that's pretty much what I want to do:

I have never worked with Objective-C / Swift before, but is it not possible or did it just not work?

viskin commented 7 years ago

On iOS, AFAIK you cannot get access to photo from media library as file. You can read the photo with requestImageData function, as implemented here. But access to the photo as cdvfile:// is not existent. Only as cdvphotolibrary://. It's possible to copy this data to temporary storage and then upload from there...

AndreasGassmann commented 7 years ago

Looks like you are right. I looked at cordova-plugin-camera and they are also creating a local file.

I would really like to avoid copying multiple full sized images into JS, just to pass it back to the OS again.

As mentioned I have never worked with iOS natively, but I might try to implement something like that if I have time. Is that something you would like to add to your plugin? If yes, do you have any interface in mind? I was thinking about something along the lines of getFileUri(photoIds[]): string[] which would copy the pictures and return an array with the paths.

As a side note: On android it should probably also make a copy, even if it supports returning the original URI. I had an issue with the cordova-plugin-camera where it would sometimes delete the original picture if you delete the file with the cordova-file-plugin.

viskin commented 7 years ago

Having such functionality in the plugin would be great. It will enable interop with other libraries, as a photo will be accessible with native path. About the API, I think that a. It should accept one photoId, and not array, to enable scenarios where processing only few photos a time is wanted. After all, materializing a photo will take a lot of storage. b. It looks like it should be asynchronous (with callback when file is copied to temporary storage). c. Should support deletion of created file. What do you say about materializePhoto(photoId, function(url), function(err)) // resolves to url like file:// or maybe cdvfile:// unmaterializePhoto(photoId, function(), function(err)) // resolves when file is deleted

AndreasGassmann commented 6 years ago

I implemented it in a slightly different way here: https://github.com/AndreasGassmann/cordova-plugin-photo-library/tree/nativeFileUrls

It is already being used in production and so far it works fine. I also included a change that greatly increases speed and reduces file sizes of the full sized images on android. If you have time you can take a look and give me some feedback.

flogr commented 6 years ago

Hi, i would highly appreciate the feature to get native file urls and delete images from this plugin. I currently use it an app for browsing taken images and share and delete features are needed, this is only possible with native file urls. I think this is a pretty common feature with image library views so a lot of people could have a use for it.

@AndreasGassmann can i use your branch right now? How does retrieval of native urls or deletion work?

flogr commented 6 years ago

Hi @viskin i think your suggestions for methods like materializePhoto(photoId, function(url), function(err)) // resolves to url like file:// or maybe cdvfile:// unmaterializePhoto(photoId, function(), function(err)) // resolves when file is deleted would be great and they are exactly what i need. Is there a plan to merge this feature in the near future?

Dineshrajaa commented 6 years ago

I am also in need of this nativeURL feature..

justinbiggs commented 6 years ago

Would also love to get this nativeURL feature added in.

AndreasGassmann commented 6 years ago

@flogr Sorry for the late reply, I was on vacation.

Yes, I have been using my branch in production (Android and iOS) and it seems to work without any issues so far.

I implemented it in a slightly different way:

I added 3 methods: getNativeThumbnailUrl getNativePhotoUrl purgeNativeFileCache

When you call either getNativeThumbnailUrl or getNativePhotoUrl you will get back the file:// URI to that photo. Internally it will create a copy of the original file in your apps cache directory with a cdvphotolibrary- prefix. You can then use that URI and pass it to the file or transfer plugin.

Once you are done, you can call the purgeNativeFileCache function. It will delete all files in the cache directory that start with the cdvphotolibrary- prefix.

In my case I have a queue of images that need to be uploaded and once the queue is empty, I call the cleanup function to get rid of the temporary files. At first I wanted to implement the cleanup for each individual picture, but there could have been inconsistencies if someone closed the app and interrupt the process (because you need the ID to be able to delete the cached file). So because a "global" cleanup function is needed anyway and was enough in my case, I just left it at that. But depending on the use case, a method to delete the copy of an individual picture would be nice to have.

On another note, I made a small change to the way full images are copied if you call getPhoto, so the size should be around 2.5x smaller. (In my test with an iPhone 7 Plus the original photo was 5MB, this plugin returned a picture that was 12.5MB). So displaying a full picture is noticeably faster now.

flogr commented 6 years ago

Thanks for your response @AndreasGassmann your solution seems pretty elegant. Maybe @viskin can merge it into the master branch, what do you think about that?

AndreasGassmann commented 6 years ago

@flogr I think I would have to document the changes in the readme before it can be merged. I might have time to do that in a couple of days.

For the time being, can you try out my fork/branch and check if everything works? If there are no bugs I probably won't change the code anymore, just the documentation.

justinbiggs commented 6 years ago

@AndreasGassmann probably a noob question, but when I fork and install into my plugins folder typescript complains that it can't find the function getNativePhotoUrl. Do I need to add the new functions to the PhotoLibrary.d.ts file? What about the ionic-native/photo-library folder, do I need to change anything there? Thanks in advance for any help.

AndreasGassmann commented 6 years ago

@justinbiggs Ah yeah, I didn't change the PhotoLibrary.d.ts, so the definitions there are wrong. I'll add that soon (or you can make a PR on my fork)

AndreasGassmann commented 6 years ago

I just saw the job offer on upwork.

I'm curious what kind of issue you have with my fork/branch. I created a gitter room for this project where we can discuss the problems you have. I can also provide code snippets from the project where I used this plugin if needed.

https://gitter.im/cordova-plugin-photo-library/

kevinswartz commented 6 years ago

@AndreasGassmann I also installed your fork. I'm getting an error back when trying to call getNativePhotoUrl() on a file from an icloud album - "Could not fetch the image". I also get this when calling getPhoto() or getThumbnail().

Is this a known issue for iCloud albums? I was hoping to download the image if needed, and upload it using cordova-plugin-file. Thanks for your help!

victoria168 commented 6 years ago

@AndreasGassmann Thanks for sharing. However I failed to display the output image on IOS. I've logged my case here: https://github.com/terikon/cordova-plugin-photo-library/issues/97 Have you encountered similar issue? thanks!

flogr commented 6 years ago

The best thing would be for the Librarby Plugin to return native file URLs on both platforms, Android and IOS, but without copying images again. Is this really not possible in any way? Can't quite believe this, but i've never created native plugins...

AndreasGassmann commented 6 years ago

@flogr It is definitely possible on Android, but I didn't find a way on iOS (but I have no experience with Swift/Objective C).

One possibility would be to add a new function like deleteOriginalPhoto(photoID) that takes care of it internally, without having to expose the file URI.

soulmecca commented 6 years ago

@AndreasGassmann Hi, I tried to use your branch to get the native file addresses but couldn't get it to work. I coudn't try these functions... getNativeThumbnailUrl getNativePhotoUrl purgeNativeFileCache

I am using Ionic and tried your branch with Ionic Native. Is there something that I missed?

AndreasGassmann commented 6 years ago

Ionic Native doesn't have those features included. This will only happen if it gets merged into the main branch of this repository. So for now you will have to use it without ionic native.

soulmecca commented 6 years ago

Thanks, @AndreasGassmann for your response. Okay, I tried not with Ionic native this time but have no idea how to use the functions like getNativeThumbnailUrl. What I tried was, I first used cordova.plugins.photoLibrary.getLibrary then I could get each library item through forEach loop and then tried cordova.plugins.PhotoLibrary.getNativeThumbnailUrl(libraryItem) but got nothing. I looked at PhotoLibtaty.d.ts and found there is no function like getNativeThumbnailUrl while there is one in PhotoLibrary.swift. I also tried to insert getNativeThumbnailUrl function in PhotoLibrary.d.ts but no luck. Could you please explain how to use the functions?

Thanks a lot in advance.

AndreasGassmann commented 6 years ago

The PhotoLibrary.d.ts is not updated, that's the main reason I didn't make a pull request yet.

My code looks like that (p.id is the id of a photo that I got from getLibrary):

cordova.plugins.photoLibrary.getNativePhotoUrl(
    p.id,
    (fullUrl) => {
        console.log('File URI', fullUrl);
    },
    (err) => {
        reject('Error while getting full native path occured' + err);
});

In this comment I described how it works: https://github.com/terikon/cordova-plugin-photo-library/issues/60#issuecomment-326823273