python把文件读成字节流,FTP发送Python的字节流

I want to send a file with python ftplib, from one ftp site to another, so to avoid file read/write processees.

I create a BytesIO stream:

myfile=BytesIO()

And i succesfully retrieve a image file from ftp site one with retrbinary:

ftp_one.retrbinary('RETR P1090080.JPG', myfile.write)

I can save this memory object to a regular file:

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

fot=myfile.readvalue()

But i am not able to send this stream via ftp with storbinary. I thought this would work:

ftp_two.storbinary('STOR magnafoto.jpg', myfile.getvalue())

But doesnt. i get a long error msg ending with 'buf = fp.read(blocksize)

AttributeError: 'str' object has no attribute 'read'

I also tried many absurd combinations, but with no success. As an aside, I am also quite puzzled with what I am really doing with myfoto.write. Shouldnt it be myfoto.write() ?

I am also quite clueless to what this buffer thing does or require. Is what I want too complicated to achieve? Should I just ping pong the files with an intermediate write/read in my system? Ty all

EDIT: thanks to abanert I got things straight. For the record, storbinary arguments were wrong and a myfile.seek(0) was needed to 'rewind' the stream before sending it. This is a working snippet that moves a file between two ftp addresses without intermediate physical file writes:

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

解决方案

The problem is that you're calling getvalue(). Just don't do that:

ftp_two.storbinary('STOR magnafoto.jpg', myfile)

storbinary requires a file-like object that it can call read on.

Fortunately, you have just such an object, myfile, a BytesIO. (It's not entirely clear from your code what the sequence of things is here—if this doesn't work as-is, you may need to myfile.seek(0) or create it in a different mode or something. But a BytesIO will work with storbinary unless you do something wrong.)

But instead of passing myfile, you pass myfile.getvalue(). And getvalue "Returns bytes containing the entire contents of the buffer."

So, instead of giving storbinary a file-like object that it can call read on, you're giving it a bytes object, which is of course the same as str in Python 2.x, and you can't call read on that.

For your aside:

As an aside, I am also quite puzzled with what I am really doing with myfoto.write. Shouldnt it be myfoto.write() ?

Look at the docs. The second parameter isn't a file, it's a callback function.

The callback function is called for each block of data received, with a single string argument giving the data block.

What you want is a function that appends each block of data to the end of myfoto. While you could write your own function to do that:

def callback(block_of_data):

myfoto.write(block_of_data)

… it should be pretty obvious that this function does exactly the same thing as the myfoto.write method. So, you can just pass that method itself.

If you don't understand about bound methods, see Method Objects in the tutorial.

This flexibility, as weird as it seems, lets you do something even better than downloading the whole file into a buffer to send to another server. You can actually open the two connections at the same time, and use callbacks to send each buffer from the source server to the destination server as it's received, without ever storing anything more than one buffer.

But, unless you really need that, you probably don't want to go through all that complexity.

In fact, in general, ftplib is kind of low-level. And it has some designs (like the fact that storbinary takes a file, while retrbinary takes a callback) that make total sense at that low level but seem very odd from a higher level. So, you may want to look at some of the higher-level libraries by doing a search at PyPI.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值