Kaip siųsti „multipart / form-data“ su užklausomis pythone?

Kaip siųsti kelių multipart/form-data su užklausomis pythone? Suprantu, kaip siųsti failą, bet negaliu suprasti, kaip pateikti šiuos blankus šiuo metodu.

146
12 сент. nustatė agrynchuk, rugsėjo 12 d. 2012-09-12 12:33 '12 12:33 2012-09-12 12:33
@ 6 atsakymai

Tiesą sakant, jei nurodysite parametrų files (žodyną), requests siunčia POST multipart/form-data vietoj POST application/x-www-form-urlencoded . Tačiau jūs nesinaudojate tikrais failais šiame žodyne:

 >>> import requests >>> response = requests.post('http://httpbin.org/post', files=dict(foo='bar')) >>> response.status_code 200 

ir httpbin.org leidžia jums žinoti, kurias antraštes paskelbėte; į response.json() turime:

 >>> from pprint import pprint >>> pprint(response.json()['headers']) {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Content-Length': '141', 'Content-Type': 'multipart/form-data; ' 'boundary=c7cbfdd911b4e720f1dd8f479c50bc7f', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.21.0'} 

Be to, galite papildomai kontroliuoti failo pavadinimą, turinio tipą ir papildomas antraštes kiekvienai daliai, naudodami eilutę vietoj vienos eilutės ar baito objekto. Tikimasi, kad pakete bus 2–4 elementai; failo pavadinimas, turinys, pasirinktinis turinio tipas ir papildomas antraščių žodynas.

Naudodamas šią pavadinimo formą, failo pavadinime naudoju šią formą, todėl parametro filename="..." pašalinamas iš šių dalių užklausos:

 >>> files = {'foo': 'bar'} >>> print(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8')) --bb3f05a247b43eede27a124ef8b968c5 Content-Disposition: form-data; name="foo"; filename="foo" bar --bb3f05a247b43eede27a124ef8b968c5-- >>> files = {'foo': (None, 'bar')} >>> print(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8')) --d5ca8c90a869c5ae31f70fa3ddb23c76 Content-Disposition: form-data; name="foo" bar --d5ca8c90a869c5ae31f70fa3ddb23c76-- 

files taip pat gali būti sąrašų su dviem reikšmėmis, jei jums reikia užsakymo ir (arba) kelių laukų, turinčių tą patį pavadinimą:

 requests.post('http://requestb.in/xucj9exu', files=(('foo', (None, 'bar')), ('spam', (None, 'eggs')))) 

Jei nurodysite files ir data , tai priklauso nuo data , kurie bus naudojami kuriant POST kūną, vertės. Jei data yra eilutė, tik ji bus naudojama; kitaip jie naudojami kaip data ir files , pirmiausia išvardyti data elementai.

Taip pat yra puikus requests-toolbelt , apimantis platų „Multipart“ palaikymą . Jis priima lauko apibrėžimus tuo pačiu formatu kaip ir files parametras, tačiau, skirtingai nei requests jis nustato failo pavadinimo parametro nustatymą. Be to, ji gali siųsti užklausą iš atvirų failų objektų, kur requests pirmiausia sukuria atmintyje užklausos elementą.

96
12 сент. Atsakymą pateikė Martijn Pieters 12 rugsėjis. 2012-09-12 12:59 '12 12:59 2012-09-12 12:59

Kadangi ankstesni atsakymai buvo parašyti, prašymai pasikeitė. Pažvelkite į „ Githubklaidą dėl išsamesnės informacijos ir šio komentaro .

Trumpai tariant, failų parametras užima reikšmę dict , o raktas yra formos lauko pavadinimas, o vertė yra 2, 3 arba 4 ilgių eilutė arba eilutė, kaip aprašyta POST faile su daugelio puslapių kodavimu greito paleidimo užklausose:

 >>> url = 'http://httpbin.org/post' >>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})} 

Pirmiau pateiktame pavyzdyje paketas susideda iš:

 (filename, data, content_type, headers) 

Jei reikšmė yra tik eilutė, failo pavadinimas bus toks pat kaip ir raktas, kaip parodyta žemiau:

 >>> files = {'obvius_session_id': '72c2b6f406cdabd578c5fd7598557c52'} Content-Disposition: form-data; name="obvius_session_id"; filename="obvius_session_id" Content-Type: application/octet-stream 72c2b6f406cdabd578c5fd7598557c52 

Jei reikšmė yra eilutė, o pirmasis įrašas yra None , failo pavadinimo savybė nebus įtraukta:

 >>> files = {'obvius_session_id': (None, '72c2b6f406cdabd578c5fd7598557c52')} Content-Disposition: form-data; name="obvius_session_id" Content-Type: application/octet-stream 72c2b6f406cdabd578c5fd7598557c52 
92
10 апр. Atsakymas pateikiamas runejuhl 10 Bal 2014-04-10 00:50 '14 - 0:50 2014-04-10 00:50

Norint išsiųsti POST užklausą iš kelių dalių, turite naudoti files parametrą, net jei nereikia įkelti jokių failų.

Iš pradinio užklausos šaltinio:

 multipart_form_data = { 'file2': ('custom_file_name.zip', open('myfile.zip', 'rb')), 'action': ('', 'store'), 'path': ('', '/path1') } response = requests.post('https://httpbin.org/post', files=multipart_form_data) print(response.content) 

☝ Atkreipkite dėmesį į tuščią eilutę kaip pirmąjį argumentą teksto laukų eilutėje - tai failo vardo lauko, kuriam naudojamas tik failo įkėlimas, vietovė, tačiau teksto laukams vis dar reikia tuščio vietos, kad būtų siunčiami duomenys,


Jei ši API nėra pakankamai pythoninė, arba jei norite paskelbti kelis vienodus pavadinimus, naudokite instrumentinės užklausos juostą ( pip install requests_toolbelt request_toolbelt reports_toolbelt ), kuris yra pagrindinio užklausos modulio, teikiančio transliacijos palaikymą, plėtinys. formoje, taip pat „ MultipartEncoder“, kuris gali būti naudojamas vietoj files ir kuris naudoja parametrus ir žodynus, ir files .

MultipartEncoder gali būti naudojamas sudėtinėms užklausoms su arba be faktinių apkrovos laukų. Jis turi būti priskirtas data parametrams.

45
13 марта '16 в 21:29 2016-03-13 21:29 atsakymas pateikiamas ccpizza kovo 13, 16 d. 21:29 2016-03-13 21:29

Turite naudoti įkeltos rinkmenos name atributą, kuris yra HTML svetainėje. Pavyzdys:

 autocomplete="off" name="image"> 

Ar matote name="image"> ? Ją galite rasti HTML svetainėje, kad galėtumėte atsisiųsti failą. Turite naudoti jį įkelti failą naudodami „ Multipart/form-data

scenarijus:

 import requests site = 'https://prnt.sc/upload.php' # the site where you upload the file filename = 'image.jpg' # name example 

Čia, vietoj vaizdo, pridėkite į HTML įkeltą failą.

 up = {'image':(filename, open(filename, 'rb'), "multipart/form-data")} 

Jei norite atsisiųsti atsisiuntimui skirtą mygtuką, galite jį naudoti:

 data = { "Button" : "Submit", } 

Tada paleiskite užklausą

 request = requests.post(site, files=up, data=data) 

Be to, failas sėkmingai įkeltas

4
01 мая '18 в 14:29 2018-05-01 14:29 atsakymas pateikiamas „ Skiller Dz“ gegužės 1 d. 18 d. 14:29 2018-05-01 14:29

Čia pateikiamas paprastas kodo fragmentas, skirtas atsisiųsti vieną failą su papildomais parametrais naudojant užklausas:

 url = 'https://<file_upload_url>' fp = '/Users/jainik/Desktop/data.csv' files = {'file': open(fp, 'rb')} payload = {'file_id': '1234'} response = requests.put(url, files=files, data=payload, verify=False) 

Atkreipkite dėmesį, kad nereikia aiškiai nurodyti jokio tipo turinio.

PASTABA. Norėjau pakomentuoti vieną iš pirmiau minėtų atsakymų, bet dėl ​​savo žemos reputacijos aš negalėjau, todėl čia paruošiau naują atsakymą.

0
24 янв. Atsakymą pateikė Jainik Jan 24 2019-01-24 00:59 19 „0:59 2019-01-24“ 00:59

Čia yra „Python“ kodo fragmentas, kurį reikia įkelti vieną didelį failą kaip sudėtinius duomenis. Naudojant serverio pusės „NodeJs Multer“ tarpinę programinę įrangą.

 import requests latest_file = 'path/to/file' url = "http://httpbin.org/apiToUpload" files = {'fieldName': open(latest_file, 'rb')} r = requests.put(url, files=files) 

Serverio pusėje patikrinkite dokumentaciją šiuo adresu: https://github.com/expressjs/multer, čia naudojamas vienas laukas („fieldName“), kad gautų vieną failą, kaip:

 var upload = multer().single('fieldName'); 
0
04 окт. atsakymas pateikiamas vinaymk 04 okt. 2018-10-04 18:58 '18, 18:58 pm 2018-10-04 18:58