omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Robocopy entire photo directory to NAS?

    Pythonista
    5
    21
    4380
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • margusch
      margusch @cvp last edited by

      @cvp said:

      @margusch your script needs only to store in a local file the highest date-time of the photos that you send to your NAS and only send newer photos.

      Édit: personally, I keep a thumb copy of the photo, with the same file name, after having sent to the NAS, so I know which ones is already backuped. Obviously, this works if you don't have millions of photos.

      Thats a good idea!
      Would you mind sharing your code with me?

      I am thinking if buying the app "PhotoSync" wouldn't just do the job..

      cvp 2 Replies Last reply Reply Quote 0
      • cvp
        cvp @margusch last edited by cvp

        @margusch said:

        I am thinking if buying the app "PhotoSync" wouldn't just do the job..

        It is sure that to buy Pythonista only for this job is not very profitable.

        Édit: be careful that PhotoSync may have an annual fee for some functionalities.
        Check also FileBrowser Pro with backup/sync features.

        margusch 1 Reply Last reply Reply Quote 0
        • cvp
          cvp @margusch last edited by cvp

          @margusch said:

          Would you mind sharing your code with me?

          Not easy to extract quickly needed parts of code but be sure that if/when you buy Pythonista, I could help you

          It would depend of:

          • are your photos in camera roll or local directory of Pythonista or in Files app
          • do you want to keep original
          • do you want to keep a thumb in local Pythonista file
          • how much photos
          • which solution: smb or ftp or sftp
          • sure that no duplicate file names (if yes, more complex process)
          • work with a control file or each time compare NAS directory (quickly downloaded)
          • quid if you want to delete a local photo, does the deletion on NAS must occur
          • which NAS, for instance Synology has a synchronization function included
          • etc...
          1 Reply Last reply Reply Quote 0
          • margusch
            margusch @cvp last edited by

            @cvp Thank you very much for your help!

            I will try FileBrowser Pro and PhotoSync and if they are working fine I will go with one of that.

            cvp 2 Replies Last reply Reply Quote 0
            • cvp
              cvp @margusch last edited by

              @margusch here, little quick and dirty, but tested, script

              from   ftplib import FTP
              from   objc_util import *
              import photos
              
              # get photos from NAS
              user = 'admin'
              pwd = '...'
              ip = '192.168.0.47'
              ftp = FTP(ip) # Connect NAS
              ftp.encoding = 'utf-8'
              ftp.login(user,pwd)
              remote_folder = 'Photos/'
              filesnas= ftp.nlst(remote_folder+'*')
              
              # get photos from camera roll
              for asset in photos.get_assets():
              	fname = str(ObjCInstance(asset).valueForKey_('filename'))
              	if (remote_folder+fname) not in filesnas:
              		b = asset.get_image_data(original=False)	# file as io.BytesIO
              		ftp.storbinary('STOR '+remote_folder+fname, b,blocksize=32768)
              		print('sent:',fname)
              									
              ftp.quit() # Disconnect
              
              1 Reply Last reply Reply Quote 0
              • cvp
                cvp @margusch last edited by cvp

                @margusch said:

                I will try FileBrowser Pro and PhotoSync and if they are working fine I will go with one of that.

                Compare the prices but if you know Python, you'll have a lot of fun with Pythonista for solving new ideas.

                1 Reply Last reply Reply Quote 0
                • ccc
                  ccc last edited by

                  user = 'admin'
                  pwd = '...'
                  ip = '192.168.0.47'
                  ftp = FTP(ip) # Connect NAS
                  ftp.encoding = 'utf-8'
                  # …
                  ftp.quit() # Disconnect
                  # —>
                  with FTP(host='192.168.0.47', user='admin', passwd='…', encoding='utf-8') as ftp:
                  

                  https://docs.python.org/3/library/ftplib.html#ftplib.FTP

                  cvp 3 Replies Last reply Reply Quote 0
                  • cvp
                    cvp @ccc last edited by

                    @ccc I didn't know that the quit was not mandatory. Anyway, nicer as usual.

                    1 Reply Last reply Reply Quote 0
                    • cvp
                      cvp @ccc last edited by

                      @ccc thus, even ftp.login(..) is not necessary

                      1 Reply Last reply Reply Quote 0
                      • cvp
                        cvp @ccc last edited by ccc

                        @ccc said:

                        with FTP(host='192.168.0.47', user='admin', passwd='…', encoding='utf-8') as ftp:

                        encoding not a parameter of FTP.init, thus

                        from   ftplib import FTP
                        from   objc_util import *
                        import photos
                        
                        with FTP(host='192.168.0.47', user='admin', passwd='...') as ftp:
                        	ftp.encoding='utf-8'
                        	# get photos from NAS
                        	remote_folder = 'Photos/'	
                        	filesnas= ftp.nlst(remote_folder+'*')
                        	# get photos from camera roll
                        	for asset in photos.get_assets():
                        		fname = str(ObjCInstance(asset).valueForKey_('filename'))
                        		if (remote_folder+fname) not in filesnas:
                        			b = asset.get_image_data(original=False)	# file as io.BytesIO
                        			ftp.storbinary('STOR '+remote_folder+fname, b,blocksize=32768)
                        			print('sent:',fname)									
                        
                        1 Reply Last reply Reply Quote 0
                        • ccc
                          ccc last edited by

                          Python < 3.9 did not have an encoding parameter: https://docs.python.org/3.8/library/ftplib.html#ftplib.FTP but was added in Py3.9

                          1 Reply Last reply Reply Quote 1
                          • mikael
                            mikael @margusch last edited by

                            @margusch: "build a application which gets triggered via shortcuts daily"

                            Good to note that it will (probably) not happen in the background on a locked device, so this would in effect be more like a reminder and an easier way for you to start the process.

                            cvp 2 Replies Last reply Reply Quote 0
                            • cvp
                              cvp @mikael last edited by

                              @mikael said:

                              Good to note that it will (probably) not happen in the background on a locked device

                              I think that the shortcut runs in the background of a locked device (don't remember if I had tested) but if the shortcut launchs an app, this one would not, excepted perhaps if Pyto in background mode, not tested.

                              cvp 1 Reply Last reply Reply Quote 0
                              • cvp
                                cvp @cvp last edited by cvp

                                @mikael but perhaps could you SFTP a file to the NAS via the SSH action of shortcut....

                                1 Reply Last reply Reply Quote 0
                                • cvp
                                  cvp @mikael last edited by

                                  @mikael I had tested background in locked device for this topic

                                  mikael 1 Reply Last reply Reply Quote 0
                                  • mikael
                                    mikael @cvp last edited by

                                    @cvp, thanks, really nice if so. I remember some of my earlier attempts being somewhat hit and miss.

                                    1 Reply Last reply Reply Quote 0
                                    • aldoblack
                                      aldoblack last edited by aldoblack

                                      So far this is the code that I'm using uploading with Synology REST API. It works well until Pythonista crashes when uploading photos between 900-1000.

                                      import appex
                                      import photos
                                      import requests
                                      import os
                                      import editor
                                      import sys
                                      from objc_util import *
                                      
                                      from datetime import datetime
                                      
                                      
                                      class Synology(object):
                                          def __init__(self, url, port, account, passwd):
                                              """
                                              
                                              :param url: IP/URL or Synology. So far it only supports HTTP.
                                              :param port:
                                              :param account:
                                              :param passwd:
                                              :returnv:
                                              """
                                              self.url = url
                                              self.port = port
                                              
                                              self.account = account
                                              self.passwd = passwd
                                      
                                              self.sid = None
                                      
                                              # self.session = requests.Session()
                                      
                                          def login(self):
                                              print("Logging in...")
                                      
                                              param = {
                                                  "version": "2",
                                                  "method": "login",
                                                  "account": self.account,
                                                  "passwd": self.passwd,
                                                  "session": "FileStation",
                                                  "format": "cookie"
                                              }
                                      
                                              url = f"http://{self.url}:{self.port}/webapi/auth.cgi?api=SYNO.API.Auth"
                                      
                                              r = requests.get(url, param, verify=False)
                                              r = r.json()
                                      
                                              if not r["success"]:
                                                  raise Exception("Authenticatoin failed. Note that account with 2FA enabled does not work.")
                                      
                                              print("Logging successful.")
                                      
                                              self.sid = r["data"]["sid"]
                                              return self.sid
                                      
                                          def upload_file(self, files):
                                              upload_url = f"http://{self.url}:{self.port}/webapi/entry.cgi?api=SYNO.FileStation.Upload&version=2&method=upload&_sid={self.sid}"
                                      
                                              args = {
                                                  "path": "/home/b",
                                                  "create_parents": "true",
                                                  "overwrite": "true"
                                              }
                                      
                                              # Ignore this ugly code. I am trying to figure out if I can do bulk upload in one request.
                                              file = {'file': (files[0]["fname"], files[0]["payload"], 'application/octet-stream')}
                                              # file = [('files', (x["fname"], x["payload"], "application/octet-stream")) for x in files]
                                      
                                              r = requests.post(upload_url, data=args, files=file, verify=False)
                                      
                                      
                                      
                                      def main():
                                          # if not appex.is_running_extension():
                                          # 	print("Sript is intended to be un from sharing extension.")
                                          # 	return
                                      
                                          print("Starting...")
                                          s = Synology(url="1.1.1.1", port="2000", account="user", passwd="pass")
                                          s.login()
                                              
                                          startTime = datetime.now()
                                      
                                          all_photos = photos.get_assets()
                                          images = []
                                      
                                          for idx, asset in enumerate(all_photos):
                                      
                                              if idx % 10 == 0:
                                                  print(f"Uploading... {idx}/{len(all_photos)}")
                                      
                                              fname = str(ObjCInstance(asset).valueForKey_('filename'))
                                              payload = asset.get_image_data(original=True)
                                      
                                              images = [{"fname": fname, "payload": payload}]
                                      
                                              s.upload_file(images)
                                      
                                              # print(fname)
                                      
                                          print(datetime.now() - startTime)
                                      
                                      if __name__ == "__main__":
                                          main()
                                      
                                      1 Reply Last reply Reply Quote 0
                                      • First post
                                        Last post
                                      Powered by NodeBB Forums | Contributors