1

我试图转换一些javascript代码我写到Python,但我卡在传递数据b/t PILRequests对象。如何发布带有请求的多部分POST的图像对象?

python脚本下载的图像记忆:

from PIL import Image 
import urllib2 
import cStringIO 

def fetch_image_to_memory(url): 
    req = urllib2.Request(url, headers={ 
         'User-Agent': "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11"}) 
    con = urllib2.urlopen(req) 
    imgData = con.read() 
    return Image.open(cStringIO.StringIO(imgData)) 

我喜欢,然后将其添加到form dataPOST操作。当文件在磁盘上此代码成功:

from requests_toolbelt import MultipartEncoder 
import requests 
url = 'https://us-west-2.api.scaphold.io/graphql/some-gql-endpoint' 

multipart_data = MultipartEncoder(
    fields={ 
     'query':'some-graphql-specific-query-string', 
     'variables': '{ "input": {"blobFieldName": "myBlobField" }}', 

     ## `variables.input.blobFieldName` must hold name 
     ## of Form field w/ the file to be uploaded 
     'type': 'application/json', 
     'myBlobField': ('example.jpg', img, 'image/jpeg') 
    } 
) 
req_headers = {'Content-Type':multipart_data.content_type, 
      'Authorization':'Bearer secret-bearer-token'} 
r = requests.post(url, data=multipart_data, headers=req_headers) 

然而,试图在Image对象传递从fetch_image_to_memory功能时:

'myBlobField': ('example.jpg', image_object, 'image/jpeg') 

...我得到的错误:

Traceback (most recent call last): 
    File "test-gql.py", line 38, in <module> 
    'myBlobField': img 
    File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 119, in __init__ 
    self._prepare_parts() 
    File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 240, in _prepare_ 
parts 
    self.parts = [Part.from_field(f, enc) for f in self._iter_fields()] 
    File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 488, in from_fiel 
d 
    body = coerce_data(field.data, encoding) 
    File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 466, in coerce_da 
ta 
    return CustomBytesIO(data, encoding) 
    File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 529, in __init__ 
    buffer = encode_with(buffer, encoding) 
    File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 410, in encode_wi 
th 
    return string.encode(encoding) 
AttributeError: 'JpegImageFile' object has no attribute 'encode' 

我知道从open() docs,它返回一个file类型的对象,但我只能看到PILImage转换为file是通过使用save(),它将它写入磁盘。我可以写入磁盘,但我宁愿避免这一步,因为我正在处理大量的图像。

是否可以将Image对象转换为file类型?或者具有类似效果的其他解决方法?

回答

2

MultipartEncoder可以带一个字节的字符串或一个文件对象,但一个PIL图像对象既不是。

你必须先创建一个内存中的文件对象:

from io import BytesIO 

image_file = BytesIO() 
img.save(image_file, "JPEG") 
image_file.seek(0) 

然后在后期使用image_file

​​
+0

感谢马亭。如果这种技术比仅仅将文件写入磁盘并使用'open()'更有意义,那么你是否知道自己的头脑?另外:我认为第二行应该是'image_file = BytesIO()',不是吗? – Brandon

+1

@Brandon:是的,对于错字感到抱歉。内存中的文件将比写入磁盘更快。你已经有了内存,你可以在'fetch_image_to_memory()'之前将数据读入内存。 –

相关问题