Forum Archive

Upload any files from Any App via Pythonista Script to my Raspberry Pi connected Harddisk

henryaukc

Hi All,

I am a newbie for Pythonista and stopped using it for a few months (just due to busy work). I would like to see if I can make a script to upload file from my iPad in any apps to my Raspberry Pi connected harddisk. I would like to know if it is possible to use the Share Sheet from any apps to invoke this Pythonista script to upload the file to my raspberry?

I can upload the file to my Raspberry through SFTP. Should I use the module "paramiko" to do it? Can I transfer the file byte by byte or I need to wait the original app to transfer the whole file to Pythonista so that I can upload to my raspberry? Can anyone give me some clues? Thanks a lot.

cvp

This very little script does exactly what you want:
- from any app which can share a file
- share
- Run Pythonista script
- either you have already configured this script or you select it in 'All scripts'
- and the file will be uploaded to your FTP server

# coding: utf-8
import appex
import console
import os
import ui
from ftplib import FTP

def main():     

    # Sharing: receive file 
    fil = appex.get_file_path() 
    if fil == None:
        print('no file passed')
        return

    server = 'Your ip'
    user = 'Your user'
    pwd = 'your password'
    server_file = os.path.basename(fil)

    try:
        ftp = FTP(server) #connect
        ftp.encoding = 'utf-8'
        ftp.login(user,pwd)
        ipad_file = open(fil,'rb')
        ftp.storbinary('STOR '+server_file,ipad_file,blocksize=8192)
        ipad_file.close()
        ftp.close() 
    except Exception as e:
        print(str(e))

    appex.finish()

if __name__ == '__main__':
    main()
scj643

I have the same kinda script except mine uses SFTP to upload.

henryaukc

Thanks a lot @cvp ! I will try to modify using SFTP.

Hi @scj643, should I use the following method?

putfo(fl, remotepath, file_size=0, callback=None, confirm=True)
Copy the contents of an open file object (fl) to the SFTP server as remotepath. Any exception raised by operations will be passed through.

The SFTP operations use pipelining for speed.

Parameters:
fl – opened file or file-like object to copy
remotepath (str) – the destination path on the SFTP server
file_size (int) – optional size parameter passed to callback. If none is specified, size defaults to 0
callback (callable) – optional callback function (form: func(int, int)) that accepts the bytes transferred so far and the total bytes to be transferred (since 1.7.4)
confirm (bool) – whether to do a stat() on the file afterwards to confirm the file size (since 1.7.7)
Returns:
an SFTPAttributes object containing attributes about the given file.

henryaukc

```

coding: utf-8

import appex
import console
import os
import ui
import paramiko
from io import BytesIO

def UploadCallBack(tran_bytes, total_bytes):
print("Bytes Transferred:" +tran_bytes + "\nTotal Bytes:" + total_bytes)

def main():

# Sharing: receive file
input_file = appex.get_file_path() 
if input_file == None:
    print('no file passed')
    return


# SFTP Configuration

host = '192.168.1.x'
port = 22
password = 'password'
username = 'Username'
remoteFilePath = '/media/sda/'

server_file = os.path.basename(input_file)
filesize = os.path.getsize(input_file)

print("server_file:" + server_file)

print("Starting to upload the file:" + input_file + "(Size: ", end='')
print(filesize, end='')
print(")... ")

try:
    transport = paramiko.Transport((host, port))

    transport.connect(username = username, password = password)

    sftp = paramiko.SFTPClient.from_transport(transport,max_packet_size=8*1024*1024)

    ''' sftp.open()

    while with open(input_file, 'rb') as ipad_file:

        read(ipad_file,  )
    '''
    #sftp.putfo(ipad_file, remoteFilePath + server_file, callback=UploadCallBack(int, int ))
    ipad_file = open(input_file, 'rb')

    sftp.putfo(ipad_file, remoteFilePath + server_file)

    ipad_file.close()
    sftp.close()

    transport.close()
    print('Upload done!')

except Exception as e:
    print(str(e))

appex.finish()

if name == 'main':
main()```

henryaukc

This is my script. It works but slow as hell (maybe 40kb/s). Any suggestions? I would like to show the progress of upload too but can't figure out how to use the callback yet...

cvp

That's how I do

# coding: utf-8
import appex
import console
import os
import ui
from ftplib import FTP

class MyView(ui.View):
    global file_path,loc_dir,books,lus_sur_ipad,authors_without_book

    def __init__(self,w,h):
        self.width = w
        self.height = h

        # Message Label for my_hud_alert
        msg = ui.Label(name='msg_label')
        msg.frame = (50,50,w-2*50,40)
        msg.background_color=(0.00, 0.50, 1.00, 0.5)    
        msg.bg_color = 'bisque'     
        msg.alignment = ui.ALIGN_CENTER
        msg.font= ('Courier-Bold',20)
        msg.hidden = True
        self.add_subview(msg)

        # progressbar
        progress_bar = ui.Label(name='progress_bar', flex='') 
        progress_bar.background_color=(0.00, 0.50, 1.00, 0.5)
        progress_bar.bg_color=(0.00, 0.50, 1.00, 0.5)
        progress_bar.hidden = True
        self.add_subview(progress_bar)

    def will_close(self):
        appex.finish()

def callback(p):            # only one system parameter = buffer sent/receive
    global my_ui_view,total_file_size,transmit_file_size
    transmit_file_size = transmit_file_size + len(p)
    if my_ui_view['progress_bar'].hidden:
        my_ui_view['progress_bar'].x = my_ui_view['msg_label'].x
        my_ui_view['progress_bar'].y = my_ui_view['msg_label'].y
        my_ui_view['progress_bar'].height = my_ui_view['msg_label'].height
        my_ui_view['msg_label'].hidden = False
        my_ui_view['progress_bar'].hidden = False
        my_ui_view['progress_bar'].bring_to_front() 
    my_ui_view['progress_bar'].width = my_ui_view['msg_label'].width *  (transmit_file_size/total_file_size)
    if transmit_file_size == total_file_size:
        my_ui_view['msg_label'].hidden = True               # hide msg
        my_ui_view['progress_bar'].hidden = True    # hide progress bar 

def main(): 
    global my_ui_view,total_file_size,transmit_file_size

    w, h = (540,620)
    disp_mode = 'sheet' 
    my_ui_view = MyView(w,h)
    my_ui_view.background_color='white'
    my_ui_view.name = 'Upload'
    my_ui_view.present(disp_mode,hide_title_bar=False)

    # Sharing: receive file 
    fil = appex.get_file_path() 
    if fil == None:
        print('no file passed')
        return

    server = 'Xxxxx'
    user = 'Xxxxx'
    pwd = 'xxxx'
    server_file = os.path.basename(fil)
    my_ui_view['msg_label'].text =server_file

    try:
        ftp = FTP(server) #connect
        ftp.encoding = 'utf-8'
        ftp.login(user,pwd)
        ipad_file = open(fil,'rb')
        transmit_file_size = 0
        total_file_size = os.path.getsize(fil)
        ftp.storbinary('STOR '+server_file,ipad_file,blocksize=8192,callback=callback)
        ipad_file.close()
        ftp.close() 
    except Exception as e:
        print(str(e))


if __name__ == '__main__':
    main()
henryaukc

It works very well. Thanks a lot!