How to write a string to file on ftp with pysftp?
Asked Answered
S

2

10

I have a large xml file stored in a variable. I want to write it directly to an ftp using pysftp. I believe I need to use the pysftp.putfo and this needs a file like object. Here is a minimal example:

from io import StringIO
from pysftp import Connection, CnOpts

cnopts = CnOpts()
cnopts.hostkeys = None
with Connection('localhost'
                    ,username= 'admin'
                    ,password = 'test'
                    ,cnopts=cnopts
                    ) as sftp:
        sftp.putfo(StringIO('xml string'))

I get the following error:

TypeError: Expected unicode or bytes, got None

What am I doing wrong? And is there maybe a simpler and better way of achieving my goal of writing a string variable to a file on an ftp?

Sixgun answered 20/4, 2018 at 9:0 Comment(0)
S
4

I have found one solution, not sure it is the best:

from io import StringIO
from pysftp import Connection, CnOpts

cnopts = CnOpts()
cnopts.hostkeys = None
with Connection('localhost'
                ,username= 'admin'
                ,password = 'test'
                ,cnopts=cnopts
                ) as sftp:

    f = sftp.open('/folder/filename.xml', 'wb')
    f.write('xml string')

Edit: Discovered why there is no good solution for this. Most FTP-servers will demand that you put a file directly, probably to avoid an undending stream. So my final solution was to create the file locally and use pysft put().

Sixgun answered 23/4, 2018 at 9:46 Comment(3)
Really helpful.Margarite
Hi, Could I have a question? @SixgunMargarite
Sure, if it is related to this :)Sixgun
B
18

Your first approach was valid, just specify a filename. In-memory files have no default names, and pysftp doesn't know how to name destination file.

from io import StringIO
from pysftp import Connection

with Connection('localhost', ...) as sftp:
    sftp.putfo(StringIO('xml string'), 'test.txt') 

It should just work. Also, as a side note - Paramiko (library used by pysftml) put operation is under the hood calling putfo, it's just a thin wrapper. So from the server perspective, it's totally transparent if a file was uploaded directly from FS or from memory.

Backcross answered 4/10, 2018 at 9:52 Comment(0)
S
4

I have found one solution, not sure it is the best:

from io import StringIO
from pysftp import Connection, CnOpts

cnopts = CnOpts()
cnopts.hostkeys = None
with Connection('localhost'
                ,username= 'admin'
                ,password = 'test'
                ,cnopts=cnopts
                ) as sftp:

    f = sftp.open('/folder/filename.xml', 'wb')
    f.write('xml string')

Edit: Discovered why there is no good solution for this. Most FTP-servers will demand that you put a file directly, probably to avoid an undending stream. So my final solution was to create the file locally and use pysft put().

Sixgun answered 23/4, 2018 at 9:46 Comment(3)
Really helpful.Margarite
Hi, Could I have a question? @SixgunMargarite
Sure, if it is related to this :)Sixgun

© 2022 - 2024 — McMap. All rights reserved.