Forum Archive

Pythonista Upload Photos from Library

DavinE

Hey Guys,

i Have a new idea and a new Question xD

is it Possible to select multiple Photos from my complete Photo-Library and upload it to my server via ftps ?

i found this on the documentation:

import photos
assets = photos.pick_asset(title='Pick some assets', multi=True)
print(assets)

here i can select some vids and pics.
but how i get the path of the files to use it in ftp ?
and nice to have were to rename each file

is this possible ?

cvp

@DavinE use, for each asset, something like

            filename = str(ObjCInstance(asset).valueForKey_('filename'))
            pil = asset.get_image()
            pil.save(filename, quality=95)

Then you can send your local file and remove it after.

DavinE

@cvp said:

@DavinE use, for each asset, something like
filename = str(ObjCInstance(asset).valueForKey_('filename')) pil = asset.get_image() pil.save(filename, quality=95)
Then you can send your local file and remove it after.

Yeah this works.
but the name of the file are: IMG_1421.JPG..

is it possible without saving the file local to send it and rename it ?

when i get more images or only at one i do not know the name of it ?

DavinE

@cvp,

this is my code:

import os, sys
import photos

assets = photos.pick_asset(title='Pick some assets', multi=True)
print(f'assets: {assets}')
for asset in assets:
    pil = asset.get_image(original=False)
    pil.show()
    #print(filename)
    filename = 'test.PNG'
    pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)

this works good but is it possible to change the filename like this:

    pil = asset.get_image(original=False)
    console.quicklook(pil)
    #print(filename)
    filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG')
    pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)

or better show the image in console.input_alert thus you know what you are renaming ?

cvp

@DavinE for the file name, testing your code would be the best answer πŸ™„

cvp

@DavinE console.quicklook needs a path, not a pil

    filename = 'test.PNG'
    console.quicklook(filename)
cvp

@DavinE this works

    pil = asset.get_image(original=False)
    #pil.show()
    #print(filename)
    filename = 'test.PNG'
    console.quicklook(filename)
    filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG')
    pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)
DavinE

@cvp said:

@DavinE this works
pil = asset.get_image(original=False) #pil.show() #print(filename) filename = 'test.PNG' console.quicklook(filename) filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG') pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)

No this works not because console.quicklook(filename) did not exists pil.save is called later...
i think what i want to do this don't works..

DavinE

@cvp said:

@DavinE console.quicklook needs a path, not a pil
filename = 'test.PNG' console.quicklook(filename)

i Know i get an error xD

DavinE

@cvp said:

@DavinE for the file name, testing your code would be the best answer πŸ™„

i removed the Question ^^ i'm too fast

cvp

@DavinE thus, all is ok?

cvp

@DavinE said:

No this works not because console.quicklook(filename) did not exists pil.save is called later...
i think what i want to do this don't works..

You are right, sorry. But you can always rename your file after saving it as local.
If you only need to upload the file and to not keep a local copy, usealways the same temp name for local save, thus the quicklook will work.

get asset
pil.save as local tempname
quicklook tempname
ask name
Upload to name
remove tempname local

DavinE

@cvp said:

@DavinE said:

No this works not because console.quicklook(filename) did not exists pil.save is called later...
i think what i want to do this don't works..

You are right, sorry. But you can always rename your file after saving it as local.
If you only need to upload the file and to not keep a local copy, usealways the same temp name for local save, thus the quicklook will work.

yes, i got the same idea ;)

here's the code:

assets = photos.pick_asset(title='Pick some assets', multi=True)
print(f'assets: {assets}')
for asset in assets:
    pil = asset.get_image(original=False)
    pil.save(os.path.join(os.path.dirname(sys.argv[0]), 'Images', filename), quality=95)

    for image in os.listdir(os.path.join(os.path.dirname(sys.argv[0]), 'Images')):
        console.quicklook((os.path.join(os.path.dirname(sys.argv[0]), 'Images', image)))
        filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG')
        # Upload......

Thanks for your help @cvp

cvp

@DavinE I have edited my post just before reading your last one

DavinE

@cvp the post above yours or which one ?

cvp

If you want to ftp upload the picked photos, I think you get the asset a binary data and to upload it without passing via a local copy.
Of course, if you want to show the photo without a local file, you can't use quicklook but an ImageView could be sufficient to show the image....

cvp

@DavinE said:

the post above yours or which one ?

Forget it because you found a solution

cvp

I don't have any FTP server accessible just now, but you can test this

#pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)
temp = io.BytesIO()
pil.save(temp, format='JPEG', quality=95)
temp.seek(0)
#session.storbinary('STOR xxxxx.jpg' , temp)

The pil.save needs a format because, without file name, file type would be unknown

cvp

Please, if you try this one, please let me know if it is ok

import console
import os, sys
import photos
import io
import ui

assets = photos.pick_asset(title='Pick some assets', multi=True)
for asset in assets:
    pil = asset.get_image(original=False)
    iv = ui.ImageView()
    iv.image = asset.get_ui_image()
    iv.present('fullscreen')
    #pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)
    temp = io.BytesIO()
    pil.save(temp, format='JPEG', quality=95)
    temp.seek(0)
    filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG')
    #session.storbinary('STOR '+filename , temp)
DavinE

@cvp said:

Please, if you try this one, please let me know if it is ok

```
import console
import os, sys
import photos
import io
import ui

assets = photos.pick_asset(title='Pick some assets', multi=True)
for asset in assets:
pil = asset.get_image(original=False)
iv = ui.ImageView()
iv.image = asset.get_ui_image()
iv.present('fullscreen')
#pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)
temp = io.BytesIO()
pil.save(temp, format='JPEG', quality=95)
temp.seek(0)
filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG')
#session.storbinary('STOR '+filename , temp)
```

this looks nice.
i try it.

DavinE

@cvp said:

Please, if you try this one, please let me know if it is ok

```
import console
import os, sys
import photos
import io
import ui

assets = photos.pick_asset(title='Pick some assets', multi=True)
for asset in assets:
pil = asset.get_image(original=False)
iv = ui.ImageView()
iv.image = asset.get_ui_image()
iv.present('fullscreen')
#pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)
temp = io.BytesIO()
pil.save(temp, format='JPEG', quality=95)
temp.seek(0)
filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG')
#session.storbinary('STOR '+filename , temp)
```

This works very well @cvp!
i do not need to remove any files ?

goes this example also with the (german: Dateien App) Files App to select any file on my Documents ?

cvp

@DavinE said:

This works very well

I have also just tested successfully 😁

cvp

@DavinE said:

i do not need to remove any files ?

No because you did not create any file, you work in memory

cvp

@DavinE said:

goes this example also with the (german: Dateien App) Files App to select any file on my Documents ?

It should also be ok, but you would have to select a file and read it as binary file

DavinE

@cvp said:

@DavinE said:

i do not need to remove any files ?

No because you did not create any file, you work in memory

this code snippet io.BytesIO()do that ?

cvp

@DavinE said:

This works very well

Did you test with ftp storbinary? I did it and it is ok

cvp

@DavinE said:

this code snippet io.BytesIO()do that ?

Yes, it creates a bytes buffer accessible like a file object, with seek, read... what is needed by ftp.storbinary

DavinE

@cvp said:

@DavinE said:

goes this example also with the (german: Dateien App) Files App to select any file on my Documents ?

It should also be ok, but you would have to select a file and read it as binary file
read it as binary file

the same way above ?
and how can i select them in Pythonista ?

DavinE

@cvp said:

@DavinE said:

This works very well

Did you test with ftp storbinary? I did it and it is ok

yeah i tried it works ;)

DavinE

@cvp said:

Yes, it creates a bytes buffer accessible like a file object, with seek, read... what is needed by ftp.storbinary

Thanks for your time to explain my that

cvp

@DavinE said:

the same way above ?
and how can i select them in Pythonista ?

No no. Picked phoTos reads for you the photo file in memory (asset)

If you want to get all files of Files App, you will need to define an external open folder in the left browser of Pythonista.

cvp

Or you select a file in the Files App, not in Pythonista, and you share it to a Pythonista script which will receive the url of a temporary copy of the file, that you can upload to your ftp server.
But in this case, the selection is done in the Files App.

DavinE

@cvp said:

@DavinE said:

the same way above ?
and how can i select them in Pythonista ?

No no. Picked phoTos reads for you the photo file in memory (asset)

If you want to get all files of Files App, you will need to define an external open folder in the left browser of Pythonista.

okay and then Pythonista have access to this folder and can Upload it ?
do you know the path of this external folders ?

cvp

@DavinE said:

do you know the path of this external folders ?

It depends on which folder?

Example, I have a Numbers folder in iCloud Drive, for the standard app. Path is
/private/var/mobile/Library/Mobile Documents/com~apple~Numbers/Documents/Myfile.numbers

cvp

@DavinE said:

and then Pythonista have access to this folder and can Upload it ?

Yes if you define the wanted folder in your external folders

DavinE

@cvp Works this also with an folder on iPhone not in iCloud ?

cvp

@DavinE said:

Works this also with an folder on iPhone not in iCloud ?

I guess yes

cvp

Example of path of an image of a private folder on my iPad

/private/var/mobile/Containers/Shared/AppGroup/EF3F9065-AD98-4DE3-B5DB-21170E88B77F/File Provider Storage/Photos vacances/20200728_140243.jpg

And copy works

DavinE

@cvp
i Tried it too and works for me ;)
but my number is different on my iPhone i need to look how i get my Paths on local because i got 6 different Devices xD

cvp

@DavinE said:

my number is different on my iPhone

Sure, different on each idevice

DavinE

@cvp,

i Have a Problem with the present of the view...
i get this error:

in uploadCustomerFiles_FTP__ACTION_Button
    iv.present('fullscreen')
ValueError: View is already being presented or animation is in progress

can i use in my main view another view ?

The first Images Present works but the second one creates the error

cvp

@DavinE said:

can i use in my main view another view ?

You have to close the presented view before you present another one

cvp

@DavinE try so

iv = ui.ImageView()
iv.present('fullscreen')
assets = photos.pick_asset(title='Pick some assets', multi=True)
for asset in assets:
    pil = asset.get_image(original=False)
    iv.image = asset.get_ui_image()
    #pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)
    temp = io.BytesIO()
    pil.save(temp, format='JPEG', quality=95)
    temp.seek(0)
    filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG')
    ftp.storbinary('STOR Films/Divers/'+filename , temp)
iv.close()
DavinE

@cvp said:

@DavinE try so
iv = ui.ImageView() iv.present('fullscreen') assets = photos.pick_asset(title='Pick some assets', multi=True) for asset in assets: pil = asset.get_image(original=False) iv.image = asset.get_ui_image() #pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95) temp = io.BytesIO() pil.save(temp, format='JPEG', quality=95) temp.seek(0) filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG') ftp.storbinary('STOR Films/Divers/'+filename , temp) iv.close()

lol.. This works ^^
i used it like this:

assets = photos.pick_asset(title='Pick some assets', multi=True)
for asset in assets:
    pil = asset.get_image(original=False)
    iv = ui.ImageView()
    iv.image = asset.get_ui_image()
    iv.present('fullscreen')
    #pil.save(os.path.join(os.path.dirname(sys.argv[0]), filename), quality=95)
    temp = io.BytesIO()
    pil.save(temp, format='JPEG', quality=95)
    temp.seek(0)
    filename = '%s%s' % (console.input_alert('Rename File', 'Message: rename File', hide_cancel_button=False), '.PNG')
    ftp.storbinary('STOR Films/Divers/'+filename , temp)
    iv.close()

but thus i get the error ^^
Thanks again @cvp

cvp

@DavinE said:

lol.. This works

Only one view, used for all photos, one after one.

Your (my previous) script created a new view for each photo and we present the next one before the previous one is fully closed, known problem.

cvp

@DavinE If you want a file picker, you can use this one and passing your "On my iDevice" folder, like

    file = file_picker_dialog('On your iDevice', root_dir='/private/var/mobile/Containers/Shared/AppGroup/EF3F9065-AD98-4DE3-B5DB-21170E88B77F/File Provider Storage')
DavinE

@cvp said:

@DavinE said:

lol.. This works

Only one view, used for all photos, one after one.

Your (my previous) script created a new view for each photo and we present the next one before the previous one is fully closed, known problem.

ah oaky..
now i know it xD

DavinE

@cvp said:

@DavinE If you want a file picker, you can use this one and passing your "On my iDevice" folder, like
file = file_picker_dialog('On your iDevice', root_dir='/private/var/mobile/Containers/Shared/AppGroup/EF3F9065-AD98-4DE3-B5DB-21170E88B77F/File Provider Storage')

i take a look on this ;) ty

DavinE

@cvp,

I have a Problem....
my Code:

              assets = photos.pick_asset(title='Bitte wΓ€hle deine Bilder aus', multi=True)
                iv = ui.ImageView()
                iv.present('fullscreen')
                for asset in assets:
                    pil = asset.get_image(original=False)
                    iv.image = asset.get_ui_image()
                    temp = io.BytesIO()
                    pil.save(temp, format='JPEG', quality=95)
                    temp.seek(0)
                    filename = '%s%s' % (console.input_alert('Bennung des Bildes', 'Gib deinem Bild einen Namen', hide_cancel_button=False), '.JPEG')
                    self.connection_FTP.storbinary('STOR '+f'{self.subDirCustomer_Bilder}/{filename}', temp, blocksize=32768)
                iv.close()

doesn't work anymore... but i don't get an error or something...
but i don't know why

did you maybe see anything ?
I tried this code and it works but now... nothing....

DavinE

my mistake...

my Drive Client did not work :(

cvp

@DavinE ok, thus, good luck

DavinE

@cvp Hey,

I have a Question about the photos Picker..

Is it Possible to select a Folder from my Albums... and not all of them ?
do you know something about that ?

cvp

@DavinE said:

Possible to select a Folder from my Albums

Do you want to say "select an Album?"

If yes, try

import photos
albums = photos.get_albums()
for album in albums:
    #print(album.title)
    if album.title == 'MyAlbum':
        photos.pick_asset(assets=album)
cvp

@DavinE Is that what you wanted?

DavinE

@cvp Yes, this is Perfect xD
Thanks ^^

p.s. Load complete Folders is not possible or ?

cvp

@DavinE said:

Folders

I have a problem when you use the word folder because Apple supports folders of albums...

cvp

@DavinE said:

Load complete Folders

Sorry, but I don't understand what you want: what is load, complete, folder s

DavinE

@cvp
I mean in the Photos app you can create Folder's with Albums right ?
and my question is load or Display the Folder Albums.

do you understand now what i mean ?

But it's not bad if not.
I can do that with just one album without any additional folders

cvp

@DavinE I've never seen something mentioned folders in Pythonista photos module, perhaps too old.
But I guess it should be possible viaObjectiveC.
Personally, I don't know how to create a folder in Photos.

DavinE

@cvp, no It's okay i use your code with one Album and remove the Photos in it when i uploaded it

with Asset.delete() this is possible or ?

cvp

@DavinE said:

with Asset.delete() this is possible or ?

It should be...after a confirmation. The best way to be sure is to try on a picked photo

DavinE

@cvp i do some test Photos xD sure is sure ^^

thanks for your help xD