【问题标题】:How do I post an Image object with a multi-part POST with Request?如何使用请求的多部分 POST 发布图像对象?
【发布时间】:2017-05-11 03:19:15
【问题描述】:

我正在尝试将我写的一些 javascript 代码转换为 Python,但在传递数据 b/t PILRequests 对象时卡住了。

我的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 data 以进行POST 操作。当文件在磁盘上时,此代码成功:

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)

但是,当尝试从fetch_image_to_memory 函数传入Image 对象时:

 '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 类型的对象,但我可以在PIL 中看到从Image 转换为file 的唯一方法是使用save(),它将其写入磁盘。我可以写入磁盘,但我宁愿避免这一步,因为我要处理很多图像。

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

【问题讨论】:

    标签: python python-2.7 python-requests python-imaging-library


    【解决方案1】:

    MultipartEncoder 可以接受字节字符串或文件对象,但PIL 图像对象两者都不是。

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

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

    然后在帖子中使用image_file

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

    【讨论】:

    • 感谢 Martijn。如果这种技术比将文件写入磁盘并使用open() 更快/更慢,您是否知道?另外:我认为第二行应该是 image_file = BytesIO() ,不是吗?
    • @Brandon:是的,抱歉打错了。内存中的文件将比将其写入磁盘要快。你已经有了内存,你之前在fetch_image_to_memory()把数据读入内存了。
    猜你喜欢
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    相关资源
    最近更新 更多