ftp发送python bytesio流

jos*_*ose 7 python memory file ftplib bytesio

我想从一个ftp站点向另一个ftp站点发送带有python ftplib的文件,以避免文件读/写过程.

我创建了一个BytesIO流:

myfile=BytesIO()
Run Code Online (Sandbox Code Playgroud)

我使用retrbinary成功从ftp站点检索图像文件:

ftp_one.retrbinary('RETR P1090080.JPG', myfile.write)
Run Code Online (Sandbox Code Playgroud)

我可以将此内存对象保存为常规文件:

fot=open('casab.jpg', 'wb')

fot=myfile.readvalue()
Run Code Online (Sandbox Code Playgroud)

但我无法通过ftp与storbinary发送此流.我认为这会奏效:

ftp_two.storbinary('STOR magnafoto.jpg', myfile.getvalue())
Run Code Online (Sandbox Code Playgroud)

但不是.我得到一个很长的错误消息msg结尾'buf = fp.read(blocksize)AttributeError:'str'对象没有属性'read'

我也试过很多荒谬的组合,但没有成功.顺便说一句,我对myfoto.write真正做的事情也很困惑.不应该是myfoto.write()吗?

我对这个缓冲器的功能或要求也很无能为力.我想要的实现太复杂了吗?我应该在系统中使用中间写/读来ping文件吗?所有

编辑:感谢abanert,我把事情做好了.对于记录,storbinary参数是错误的,并且在发送之前需要myfile.seek(0)来"回放"流.这是一个工作片段,可以在两个ftp地址之间移动文件而无需中间物理文件写入:

import ftplib as ftp
from io import BytesIO

ftp_one=ftp.FTP(address1, user1, pass1)
ftp_two=ftp.FTP(address2, user2, pass2)
myfile=BytesIO()
ftp_one.retrbinary ('RETR imageoldname.jpg', myfile.write)
myfile.seek(0)
ftp_two.storbinary('STOR imagenewname.jpg', myfile)
ftp_one.close()
ftp_two.close()
myfile.close()
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 7

问题是你正在打电话getvalue().只是不要这样做:

ftp_two.storbinary('STOR magnafoto.jpg', myfile)
Run Code Online (Sandbox Code Playgroud)

storbinary需要一个可以调用的类文件对象read.

幸运的是,你有这样一个对象myfile,一个BytesIO.(从你的代码来看,事情的顺序并不完全清楚 - 如果这不能正常工作,你可能需要myfile.seek(0)或以不同的模式或其他方式创建它.但除非你做错了BytesIO,storbinary否则它会起作用.)

但是myfile,你过去了,而不是过去myfile.getvalue().并且getvalue"返回bytes包含缓冲区的全部内容."

因此,不是给出storbinary它可以调用的类文件对象,而是read给它一个bytes对象,当然它与strPython 2.x中的对象相同,你不能调用read它.


对你而言:

顺便说一句,我对myfoto.write真正做的事情也很困惑.不应该是myfoto.write()吗?

看看文档.第二个参数不是文件,它是一个回调函数.

回调函数被调用用于接收,具有一个字符串参数给出数据块的每个数据块.

你想要的是一个将每个数据块附加到末尾的函数myfoto.虽然你可以编写自己的函数来做到这一点:

def callback(block_of_data):
    myfoto.write(block_of_data)
Run Code Online (Sandbox Code Playgroud)

......很明显,这个函数与myfoto.write方法完全相同.所以,你可以自己传递那个方法.

如果您不了解绑定方法,请参阅教程中的方法对象.


这种灵活性,看起来很奇怪,让你做的事情比将整个文件下载到缓冲区以发送到另一台服务器更好.实际上,您可以同时打开这两个连接,并使用回调将每个缓冲区从源服务器发送到目标服务器,而不会存储任何多个缓冲区.

但是,除非你真的需要,否则你可能不想经历所有这些复杂性.

事实上,总的来说,ftplib是一种低级别的.并且它有一些设计(比如storbinary采用文件,同时retrbinary进行回调的事实)在较低级别上完全有意义但从较高级别看起来很奇怪.因此,您可能希望通过在PyPI上进行搜索来查看一些更高级别的库.