การโพสต์ไฟล์โดยใช้คำขอ python และ json

ฉันได้รับคำสั่ง curl ต่อไปนี้ซึ่งเป็นส่วนหนึ่งของเอกสารประกอบ API และฉันกำลังพยายามใช้งานโดยใช้ไลบรารีคำขอ

curl -v --cookie cookie.txt -X POST -H 'Accept: application/json' -F 'spot[photo]'[email protected] -F 'spot[description]'=spot_description -F 'spot[location_id]'=9  -F 'spot[categories][]'='See the Sights' -F 'spot[categories][]'='Learn Something' http://some.server.com/api/v1/spots

รหัสหลามของฉันมีลักษณะดังนี้:

import requests
import json

_user = 'redacted'
_password = 'redacted'
_session = requests.session()
_server = 'http://some.server.com'

_hdr = {'content-type': 'application/json', 'accept': 'application/json'}

_login_payload = {
    'user': {
        'email': _user,
        'password': _password
    }
}
r = _session.post(_server + "/users/sign_in", data=json.dumps(_login_payload), headers=_hdr)
print json.loads(r.content)

_spot_payload = {
    'spot': {
        'photo': '@rails.gif',
        'description': 'asdfghjkl',
        'location_id': 9,
        'categories': ['See the Sights',]
    }
}
r = _session.post(_server + '/api/v1/spots', data=json.dumps(_spot_payload), headers=_hdr)
print json.loads(r.content)

ฉันได้ยินมาว่าคุณสามารถใช้ open('file').read() เพื่อโพสต์ไฟล์ได้ แต่ตัวเข้ารหัส json ไม่ชอบสิ่งนี้มากนัก และฉันไม่แน่ใจเกี่ยวกับวิธีการแก้ไข


person Leah    schedule 18.04.2012    source แหล่งที่มา
comment
ที่เกี่ยวข้อง: การใช้ไลบรารีคำขอ Python เพื่อโพสต์ไฟล์ข้อความ   -  person Piotr Dobrogost    schedule 20.04.2012


คำตอบ (1)


C:\>cat file.txt
Some text.

เมื่อคุณออกคำสั่งนี้:

C:\>curl -X POST -H "Accept:application/json" -F "spot[photo][email protected]"
-F "spot[description]=spot_description" http://localhost:8888

สิ่งที่ถูกส่งไปมีลักษณะดังนี้:

ตัวแทนผู้ใช้ POST / HTTP/1.1: curl/7.25.0 (i386-pc-win32) libcurl/7.25.0 OpenSSL/0.9.8u zlib/1.2.6 libssh2/1.4.0 โฮสต์: localhost:8888 ยอมรับ: application/ json ความยาวเนื้อหา: 325 คาดหวัง: 100 ดำเนินการต่อประเภทเนื้อหา: multipart/form-data; ขอบเขต=--------------------------------e71aebf115cd

---------------------------------- e71aebf115cd การจัดการเนื้อหา: form-data; ชื่อ = "จุด [ภาพถ่าย]"; filename="file.txt" ประเภทเนื้อหา: text/plain

ข้อความบางส่วน ---------------------------------- e71aebf115cd การจัดการเนื้อหา: form-data; ชื่อ = "จุด [คำอธิบาย]"

spot_description ---------------------------------- e71aebf115cd--

ดังที่คุณเห็น curl ส่งคำขอโดย Content-Type ตั้งค่าเป็น multipart/form-data; คำขอ สนับสนุน การส่งไฟล์โดยใช้ Content-Type เดียวกัน คุณควรใช้อาร์กิวเมนต์ files สำหรับสิ่งนี้

(2.7) C:\>python
Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.__version__
'0.11.1'
>>> requests.post('http://localhost:8888', files={'spot[photo]': open('file.txt', 'rb')}, data={'spot[description]': 'spot_description'})
<Response [200]>

และสิ่งที่ถูกส่งไปจะเป็นดังนี้:

POST http://localhost:8888/ HTTP/1.1
Host: localhost:8888
Content-Length: 342
Content-Type: multipart/form-data; boundary=192.168.1.101.1.8000.1334865122.004.1
Accept-Encoding: identity, deflate, compress, gzip
Accept: */*
User-Agent: python-requests/0.11.1

--192.168.1.101.1.8000.1334865122.004.1
Content-Disposition: form-data; name="spot[description]"
Content-Type: text/plain

spot_description
--192.168.1.101.1.8000.1334865122.004.1
Content-Disposition: form-data; name="spot[photo]"; filename="file.txt"
Content-Type: text/plain

Some text.
--192.168.1.101.1.8000.1334865122.004.1--
person Piotr Dobrogost    schedule 19.04.2012
comment
ขอบคุณที่ชี้ให้เห็นว่าฉันลืมไปแค่ไหน =) ฉันน่าจะสามารถคิดออกเองได้ อย่างไรก็ตาม ฉันใช้เวลานานมากในการติดต่อกลับเนื่องจากไม่ได้ผลในชีวิตจริง และต้องใช้เวลาสักพักก่อนที่ฉันจะพบข้อผิดพลาดที่เป็นประโยชน์ - person Leah; 02.05.2012
comment
ข้อผิดพลาดที่เป็นปัญหาคือ TypeError: ‹เปิดไฟล์ 'logo.gif', โหมด 'rb' ที่ [hex ที่นี่]› ไม่สามารถทำให้ JSON เป็นอนุกรมได้ - person Leah; 02.05.2012
comment
ตั้งแต่นั้นมาฉันพบว่ามีปัญหาในโค้ดที่อยู่ระหว่างนั้นโดยที่ฉันส่งไฟล์ไปยังข้อมูลแทนที่จะเป็นไฟล์ เซิร์ฟเวอร์ยังคงไม่ได้รับไฟล์อย่างถูกต้อง แต่ python จะไม่ทำให้เกิดข้อผิดพลาดอีกต่อไป ฉันเกรงว่าด้วยเหตุผลด้านการรักษาความลับ ฉันไม่สามารถเปิดเผยรหัส / ที่อยู่เซิร์ฟเวอร์จริงได้ ขั้นตอนต่อไปของฉันคือการหาเครื่องมือในการจับภาพการรับส่งข้อมูลเครือข่ายที่เดินทางจากเครื่อง Mac ไปยังเซิร์ฟเวอร์ ดังนั้นฉันจึงมีบางสิ่งที่เป็นรูปธรรมที่จะมอบให้นักพัฒนา ขอบคุณสำหรับความช่วยเหลือทั้งหมดของคุณ - person Leah; 02.05.2012
comment
คุณอาจรู้ว่าเหตุใดการเข้ารหัสข้อมูลด้วย json จึงล้มเหลว: data=json.dumps({'spot[description]': 'spot_description'}) - person Alex Kreimer; 05.12.2012
comment
@AlexKreimer คุณควรถามสิ่งนี้เป็นคำถามแยกต่างหาก ตรวจสอบให้แน่ใจด้วยว่ายังไม่ได้ถูกถาม - person Piotr Dobrogost; 05.12.2012