I am trying to send a file using a POST request, which is then forwarded to a server using paramiko. I have the following code:
@app.route("/", methods=['GET', 'POST'])
def upload():
file = request.files['file']
try:
gethostbyname("servername")
except gaierror:
print(gaierror)
exit()
port = 22
if request.method == 'POST':
filePost = request.args.get('filename')
transport = paramiko.Transport("servername", port))
try:
transport.connect(username="user",password="password", hostkey=None)
sftp = paramiko.SFTPClient.from_transport(transport)
except paramiko.ssh_exception.AuthenticationException as e:
print(e)
exit()
path = '/home/'+file.filename
try:
sftp.put(file, path)
except Exception as e:
print(e)
Unfortunately nothing is uploaded. I'm afraid I have to save the file that comes from the POST request first. Is it possible to work around this? Or am I missing something?
the key/value from my post request (using Postman):
key:file
value:test.txt
The Flask save
accepts not only a file path, but also a file-like object. To obtain a file-like object representing a file on an SFTP server, use Paramiko SFTPClient.open
. That way you will stream the HTTP-uploaded file directly to the SFTP server, without having to store it temporarily on the web server.
sftp = paramiko.SFTPClient.from_transport(transport)
path = '/home/'+file.filename
with sftp.open(path, 'w+', 32768) as f:
file.save(f)
For the purpose of the 32768
argument, see Writing to a file on SFTP server opened using Paramiko/pysftp "open" method is slow.
Obligatory warning: Your direct use of low-level Transport
class bypasses SSH/SFTP server host key verification (what you even enforce by hostkey=None
). That is a security flaw. For a correct solution, use SSHClient
API and see Paramiko "Unknown Server".