使用 Paramiko put 通过 POST 请求上传文件

问题描述 投票:0回答:2

我尝试使用 POST 请求发送文件,然后使用 paramiko 将其转发到服务器。我有以下代码:

@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)

不幸的是,没有上传任何内容。恐怕我必须先保存来自 POST 请求的文件。有可能解决这个问题吗?还是我错过了什么?

我的发布请求中的键/值(使用 Postman):

key:file

value:test.txt

python flask post paramiko
2个回答
0
投票

Flask save

不仅接受文件路径,还接受类似文件的对象。要获取表示 SFTP 服务器上的文件的类文件对象,请使用 Paramiko SFTPClient.open
。这样您就可以将 HTTP 上传的文件直接流式传输到 SFTP 服务器,而无需将其临时存储在 Web 服务器上。

sftp = paramiko.SFTPClient.from_transport(transport) path = '/home/'+file.filename with sftp.open(path, 'w+', 32768) as f: file.save(f)

有关 32768

 参数的目的,请参阅
写入使用 Paramiko/pysftp“打开”方法打开的 SFTP 服务器上的文件速度很慢


强制警告:直接使用低级 Transport

 类会绕过 SSH/SFTP 服务器主机密钥验证(您甚至通过 
hostkey=None
 强制执行)。这是一个安全缺陷。如需正确的解决方案,请使用 
SSHClient
 API 并参阅 
Paramiko“未知服务器”


0
投票
您的代码将受益于一些重组和清理,实际上看起来您在这里或那里删除了一些行。

主要问题是您正在尝试通过 SFTP 传输 POST 参数中的

file

,而
sftp.put
 期望来自 FS 的文件路径作为第一个参数。

这是一个重新组织的函数,对我有用。您可以注意到,文件首先保存到 FS (

file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

),然后将相同的字符串传递到 
sftp.put
:

import os import sys import paramiko from werkzeug.utils import secure_filename from flask import Flask, render_template, redirect, url_for, request, g UPLOAD_FOLDER = '/tmp' app = Flask(__name__, static_url_path='', static_folder='static') app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER @app.route("/upload", methods=['GET', 'POST']) def upload(): if request.method == 'POST': try: file = request.files['file'] filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) transport = paramiko.Transport("sftphosthere", 22) try: transport.connect(username="usernamehere", password="passwordhere", hostkey=None) sftp = paramiko.SFTPClient.from_transport(transport) except paramiko.ssh_exception.AuthenticationException as e: return e path = '/tmp/'+file.filename try: sftp.put(os.path.join(app.config['UPLOAD_FOLDER'], filename), path) return "Sftp OK!" except Exception as e: return e except Exception as e: return e else: return "GET request" ############################################################################################################################ if __name__ == "__main__": app.run(debug=True, port=8000, host="0.0.0.0")
作为客户端发出POST请求,可以使用curl命令代替Postman:

curl -X POST http://flaskserverhere:8000/upload -F "file=@my_testfile.txt"
在运行之前,您需要在同一目录中准备一个文件(上面命令中的

my_testfile.txt

)。

© www.soinside.com 2019 - 2024. All rights reserved.