python: HTTP PUT with unencoded binary data

后端 未结 4 2479
难免孤独
难免孤独 2021-02-20 07:09

I cannot for the life of me figure out how to perform an HTTP PUT request with verbatim binary data in Python 2.7 with the standard Python libraries.

I thought I could d

相关标签:
4条回答
  • 2021-02-20 07:17

    I found out my problem. It seems there is some obscure behavior in urllib2.Request / urllib2.urlopen() (at least in Python 2.7)

    The urllib2.Request(url, data, headers) constructor seems to expect the same type of string in its url and data parameters.

    I was giving the data parameter raw data from a file read() call (which in Python 2.7 returns it in the form of a 'plain' string), but my url was accidentally Unicode because I concatenated a portion of the URL from the result of another function which returned Unicode strings.

    Rather than trying to "downcast" url from Unicode -> plain strings, it tried to "upcast" the data parameter to Unicode, and it gave me a codec error. (oddly enough, this happens on the urllib2.urlopen() function call, not the urllib2.Request constructor)

    When I changed my function call to

    # headers contains `{'Content-Type': 'application/octet-stream'}`
    r = urllib2.Request(url.encode('utf-8'), data, headers)
    

    it worked fine.

    0 讨论(0)
  • 2021-02-20 07:19

    Have you considered/tried using httplib?

    HTTPConnection.request(method, url[, body[, headers]])

    This will send a request to the server using the HTTP request method method and the selector url. If the body argument is present, it should be a string of data to send after the headers are finished. Alternatively, it may be an open file object, in which case the contents of the file is sent; this file object should support fileno() and read() methods. The header Content-Length is automatically set to the correct value. The headers argument should be a mapping of extra HTTP headers to send with the request.

    0 讨论(0)
  • 2021-02-20 07:22

    You're misreading the documentation: urllib2.Request expects the data already encoded, and for POST that usually means the application/x-www-form-urlencoded format. You are free to associate any other, binary data, like this:

    import urllib2
    
    data = b'binary-data'
    r = urllib2.Request('http://example.net/put', data,
                        {'Content-Type': 'application/octet-stream'})
    r.get_method = lambda: 'PUT'
    urllib2.urlopen(r)
    

    This will produce the request you want:

    PUT /put HTTP/1.1
    Accept-Encoding: identity
    Content-Length: 11
    Host: example.net
    Content-Type: application/octet-stream
    Connection: close
    User-Agent: Python-urllib/2.7
    
    binary-data
    
    0 讨论(0)
  • 2021-02-20 07:35

    This snipped worked for me to PUT an image:

    on HTTPS site. If you don't need HTTPS, use httplib.HTTPConnection(URL) instead.

    import httplib
    import ssl
    API_URL="api-mysight.com"
    TOKEN="myDummyToken"
    IMAGE_FILE="myimage.jpg"
    imageID="myImageID"
    URL_PATH_2_USE="/My/image/" + imageID +"?objectId=AAA"
    headers = {"Content-Type":"application/octet-stream", "X-Access-Token": TOKEN}
    imgData = open(IMAGE_FILE, "rb")
    REQUEST="PUT"
    conn = httplib.HTTPSConnection(API_URL, context=ssl.SSLContext(ssl.PROTOCOL_TLSv1))
    conn.request(REQUEST, URL_PATH_2_USE, imgData, headers)
    response = conn.getresponse()
    result = response.read()
    
    0 讨论(0)
提交回复
热议问题