我只是展示用于尝试在 sftp 中上传文件的代码:
# Check file size
def check_file_size(path):
try:
size = os.path.getsize(path)
print(f"Local file size: {size} bytes")
return size
except OSError as e:
print(f"Failed to get size of {path}: {e}")
return None
# Create an SFTP session
def create_sftp_session(hostname, port, username, password):
transport = paramiko.Transport((hostname, port))
transport.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(transport)
return sftp, transport
# Upload a file to the remote server, overwriting if it exists
def upload_file(sftp, local_path, remote_path, retries=3):
try:
# Create a temporary file and copy content to it
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
with open(local_path, 'r') as file:
temp_file.write(file.read().encode())
temp_file_path = temp_file.name
local_size = os.path.getsize(temp_file_path)
sftp.put(temp_file_path, remote_path)
remote_size = sftp.stat(remote_path).st_size
print(f"Remote file size after upload: {remote_size} bytes")
if local_size != remote_size:
print(f"Warning: Size mismatch after upload!")
# Clean up temporary file
os.remove(temp_file_path)
except IOError as e:
print(f"Failed to upload {local_path} to {remote_path}: {e}")
# Delete the local file
def delete_local_file(path):
try:
os.remove(path)
print(f"Local file {path} deleted.")
except OSError as e:
print(f"Failed to delete {path}: {e}")
# Main execution
def main():
# Create the local file
create_local_file(local_file_path)
# Set up SFTP session and upload file
sftp, transport = create_sftp_session(hostname, port, username, password)
try:
# Upload and overwrite the file
upload_file(sftp, local_file_path, remote_file_path)
finally:
sftp.close()
transport.close()
# Delete the local file
delete_local_file(local_file_path)
if __name__ == "__main__":
main()
如果针对远程服务器运行它会失败:
无法将 localfile.txt 上传到 /dir/removefile.csv:放入的大小不匹配! 94!= 141
我使用 docker 对本地 sftp 服务器运行相同的代码,它可以工作。使用 sshd-mina 的代码也是如此(此处未显示)。这是意料之外的事。为什么它对远程服务器不起作用?
我注意到的另一件事是,如果我将 upload_file 函数更改为:
# Upload a file to the remote server, overwriting if it exists
def upload_file(sftp, local_path, remote_path, retries=3):
for attempt in range(retries):
try:
# Create a temporary file and copy content to it
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
with open(local_path, 'r') as file:
temp_file.write(file.read().encode())
temp_file_path = temp_file.name
local_size = os.path.getsize(temp_file_path)
sftp.put(temp_file_path, remote_path)
remote_size = sftp.stat(remote_path).st_size
print(f"Remote file size after upload: {remote_size} bytes")
if local_size != remote_size:
print(f"Warning: Size mismatch after upload!")
# Clean up temporary file
os.remove(temp_file_path)
break # Exit loop if upload is successful
except IOError as e:
print(f"Attempt {attempt + 1} failed to upload {local_path} to {remote_path}: {e}")
if attempt < retries - 1:
print("Retrying...")
time.sleep(5) # Wait before retrying
第二次尝试就成功了! (更改在于仅在引发异常时重试)。
使用内容创建的本地文件 localfile.txt。尝试1失败 将 localfile.txt 上传到 /flex-selections/Portfolio.csv:大小不匹配 输入! 94 != 141 正在重试...上传后远程文件大小: 141 bytes 本地文件 localfile.txt 已删除。
这怎么可能?
问题出在服务器端。使用的旧版 S/FTP 前门并不完全支持所有 SFTP 命令/功能(它是具有 SFTP 增强功能的 FTP 服务器。)。
S/FTP 前门无法正确处理“put”方法中的目标目录,并且不会将“CWD”命令转发到 FTP 服务器。
解决方法:在“put()”之前添加“chdir()”或“listdir()”会强制执行“CWD”并解决问题。