使用 Paramiko put 通过 POST 请求上传文件
Upload file via POST request using Paramiko put
我正在尝试使用 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 请求的文件。有可能解决这个问题吗?还是我遗漏了什么?
来自我的 post 请求的 key/value(使用 Postman):
key:file
value:test.txt
您的代码将受益于一些重组和清理,实际上看起来您删除了一些行。
主要问题是您正在尝试通过 SFTP 从 POST 参数中获取 file
,而
sftp.put
期望来自 FS 的文件路径作为第一个参数。
这里有一个 re-organized 函数,对我有用。您可以注意到该文件首先保存到 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
)。
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
。这样您就可以将 HTTP-uploaded 文件直接传输到 SFTP 服务器,而不必将其临时存储在网络服务器上。
sftp = paramiko.SFTPClient.from_transport(transport)
path = '/home/'+file.filename
with sftp.open(path, 'w+', 32768) as f:
file.save(f)
关于 32768
论点的目的,请参阅 Writing to a file on SFTP server opened using Paramiko/pysftp "open" method is slow。
强制性警告:您直接使用 low-level Transport
class 绕过 SSH/SFTP 服务器主机密钥验证(您甚至通过 hostkey=None
).这是一个安全漏洞。对于正确的解决方案,请使用 SSHClient
API 并查看 Paramiko "Unknown Server".
我正在尝试使用 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 请求的文件。有可能解决这个问题吗?还是我遗漏了什么?
来自我的 post 请求的 key/value(使用 Postman):
key:file
value:test.txt
您的代码将受益于一些重组和清理,实际上看起来您删除了一些行。
主要问题是您正在尝试通过 SFTP 从 POST 参数中获取 file
,而
sftp.put
期望来自 FS 的文件路径作为第一个参数。
这里有一个 re-organized 函数,对我有用。您可以注意到该文件首先保存到 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
)。
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
。这样您就可以将 HTTP-uploaded 文件直接传输到 SFTP 服务器,而不必将其临时存储在网络服务器上。
sftp = paramiko.SFTPClient.from_transport(transport)
path = '/home/'+file.filename
with sftp.open(path, 'w+', 32768) as f:
file.save(f)
关于 32768
论点的目的,请参阅 Writing to a file on SFTP server opened using Paramiko/pysftp "open" method is slow。
强制性警告:您直接使用 low-level Transport
class 绕过 SSH/SFTP 服务器主机密钥验证(您甚至通过 hostkey=None
).这是一个安全漏洞。对于正确的解决方案,请使用 SSHClient
API 并查看 Paramiko "Unknown Server".