Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting native file location #60

Open
AndreasGassmann opened this issue May 12, 2017 · 25 comments
Open

Getting native file location #60

AndreasGassmann opened this issue May 12, 2017 · 25 comments

Comments

@AndreasGassmann
Copy link
Contributor

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
Copy link
Member

viskin commented May 14, 2017

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

  • getting a list of photo library items (metadata only)
  • accessing each photo as stream (e.g. as native path)
  • uploading the photo with file-transfer plugin

@viskin
Copy link
Member

viskin commented May 14, 2017

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
Copy link
Contributor Author

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

  • Loading all images from the library (metadata)
  • Displaying a list of thumbnails
  • After the user selects the pictures he wants to upload, I would like to pass them off to the file-transfer-plugin to make the upload.

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

@viskin
Copy link
Member

viskin commented May 15, 2017

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
Copy link
Contributor Author

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
Copy link
Member

viskin commented May 16, 2017

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
Copy link
Contributor Author

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
Copy link

flogr commented Aug 28, 2017

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
Copy link

flogr commented Sep 1, 2017

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
Copy link

I am also in need of this nativeURL feature..

@justinbiggs
Copy link

Would also love to get this nativeURL feature added in.

@AndreasGassmann
Copy link
Contributor Author

AndreasGassmann commented Sep 3, 2017

@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
Copy link

flogr commented Sep 4, 2017

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
Copy link
Contributor Author

@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
Copy link

justinbiggs commented Sep 7, 2017

@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
Copy link
Contributor Author

@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
Copy link
Contributor Author

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
Copy link

@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
Copy link

@AndreasGassmann Thanks for sharing. However I failed to display the output image on IOS. I've logged my case here: #97
Have you encountered similar issue? thanks!

@flogr
Copy link

flogr commented Nov 29, 2017

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
Copy link
Contributor Author

@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
Copy link

@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
Copy link
Contributor Author

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
Copy link

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
Copy link
Contributor Author

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: #60 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants