Requests: ํŒŒ์ผ ์—†์ด ๋ฉ€ํ‹ฐํŒŒํŠธ ๊ฒŒ์‹œ๋ฌผ ์ƒ์„ฑ

์— ๋งŒ๋“  2013๋…„ 01์›” 03์ผ  ยท  36์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: psf/requests

ํ˜„์žฌ ๋ฉ€ํ‹ฐํŒŒํŠธ ์–‘์‹ ์š”์ฒญ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ r = requests.post(url, data=payload, files=files)
๊ตฌ์„ฑ ์š”์†Œ๊ฐ€์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

Content-Disposition: form-data; name="file"; filename="filename.txt"
Content-Type: text/plain

content
--3eeaadbfda0441b8be821bbed2962e4d--

๊ทธ๋Ÿฌ๋‚˜ ๊ฒŒ์‹œ๋ฌผ์ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—ฐ๊ฒฐ๋œ ํŒŒ์ผ ์—†์ด ๋ฉ€ํ‹ฐํŒŒํŠธ ํ˜•์‹์ด์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

Content-Disposition: form-data; name="key1"

value1
--3eeaadbfda0441b8be821bbed2962e4d

๊ทธ๋Ÿฌ๋‚˜ ํ›„์ž๋Š” ์ „์ž ์—†์ด๋Š” ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์•„๋งˆ๋„ ํŒŒ์ผ์ด ์—†์–ด๋„ ๊ฒŒ์‹œ๋ฌผ์„ ๋‹ค์ค‘ ํŒŒํŠธ๋กœ ๋งŒ๋“œ๋Š” r = requests.post(url, data=payload, multipart=True) ์™€ ๊ฐ™์€ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ข‹์€ ์ƒ๊ฐ์ฒ˜๋Ÿผ ๋“ค๋ฆฌ๋ฉด ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์ž‘์—…์„ ํ•˜๊ฒŒ ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  36 ๋Œ“๊ธ€

์ด๊ฒƒ์€ ์ด์ „์— ๋…ผ์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค. @kennethreitz ๊ฐ€

๊ฐœ์ธ์ ์œผ๋กœ API์˜ ์‚ฌ์ „(ํŠœํ”Œ ๋ชฉ๋ก ๋“ฑ)์—์„œ ๋ฉ€ํ‹ฐํŒŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋…ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ํ‘œ๋ฉด์ ์œผ๋กœ, ๊ทธ๋“ค์ด ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์—„์ฒญ๋‚œ ๋ฉ”๋ชจ๋ฆฌ ํžˆํŠธ๊ฐ€ ์—†์–ด์•ผ ํ•˜์ง€๋งŒ, ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๊ทธ๋“ค์€ ์ด๋ฏธ ๋ฉ”๋ชจ๋ฆฌ์— ํ•˜๋‚˜์˜ ๊ฑฐ๋Œ€ํ•œ ๋ฌธ์ž์—ด์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๋‘ ๋ฒˆ์งธ๋Š” ์‹ค์ œ๋กœ ๊ทธ๋“ค์„ ์ฃฝ์ด์ง€ ์•Š์„ ๊ฒƒ์ด๊ณ  ๊ทธ๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ์•„๋‹Œ ๊ทธ๋“ค์˜ ์ž˜๋ชป์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. .

์•„๋งˆ๋„ @kennethreitz ๋Š” ๋‘ ๋ฒˆ์งธ ์†”๋ฃจ์…˜์— ๋”

์‹ค์ œ๋กœ ํ˜„์žฌ API๋Š” ํŒŒ์ผ ์ด์™ธ์˜ ๋ฉ€ํ‹ฐํŒŒํŠธ ๋ฐ์ดํ„ฐ ์ „์†ก์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ด๊ฒƒ์€ ๋‚˜์œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ #935 ๋ฐ shazow/urllib3/issues/120 ์ฐธ์กฐ

์–ด์ฉŒ๋ฉด ๋‚ด๊ฐ€ ๋ญ”๊ฐ€๋ฅผ ๋†“์น˜๊ณ  ์žˆ์„์ง€๋„ ๋ชจ๋ฅด์ง€๋งŒ ๊ทธ ๋ณ€ํ™”๋Š” ๋‚˜์—๊ฒŒ ๋‹ค์†Œ ์‚ฌ์†Œํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ์ €์žฅ์†Œ๋ฅผ ๋ถ„๊ธฐํ•˜๊ณ  ๋‚ด ๋ฒ„์ „์— ์ œ์•ˆ๋œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/spacecase/requests/commit/45b0b3ce1e76b241b323570a5fc88ae2089c3c3d
(์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋ฉด ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. ์ €๋Š” github์— ์ต์ˆ™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

๋ช‡ ๊ฐœ์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ๊ณ  api.py์˜ ๋…์ŠคํŠธ๋ง์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ด์™€ ๊ฐ™์€ ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๊นŒ?

๋ณ€๊ฒฝ ์‚ฌํ•ญ์˜ ๋ฌธ์ œ๋Š” ๊ตฌํ˜„์ด ๋ณต์žกํ•˜๋‹ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ API์˜ ์ฐจ์ด์ž…๋‹ˆ๋‹ค. ์ €๋Š” ์ด ์ง„ํ–‰ ์ค‘์ธ ํ† ๋ก ์—์„œ ์ผ์ข…์˜ ๊ฒฝ๊ณ„์— ์„œ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ ์–‘์‹ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋กœ๋“œํ•˜๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ์œผ๋ฉด ์œ ์šฉํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ํ˜„์žฌ์˜ files API๋„ ๋งค์šฐ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. . ๋‚˜๋Š” Request API์— multipart ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ๊ฐˆ ๊ธธ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ _์•Š์Šต๋‹ˆ๋‹ค_.

์†”์งํžˆ ์ €๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ์ฝ˜ํ…์ธ  ์œ ํ˜• ํ—ค๋”๋ฅผ ํ†ตํ•ด ์ œ์–ดํ•˜๊ณ  ์‹ถ์ง€๋งŒ ํ˜„์žฌ ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค 100๋ฐฐ ๋” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฝ๊ณ  ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž์—๊ฒŒ ํ˜ผ๋ž€์„ ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•ด ์šธํƒ€๋ฆฌ์— ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ์ด๊ฒƒ์„ํ•˜์ง€ ์•Š๋Š” ์ธก๋ฉด์—์„œ ์‹ค์ˆ˜๋ฅผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์™œ์š”? ์ด ๊ธฐ๋Šฅ ์š”์ฒญ์„ ์ˆ˜๋ฝํ•˜๋ฉด ๋ˆ„๊ตฐ๊ฐ€ json ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋‹ค๊ณ  ๋ถˆํ‰ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์ถ”๊ฐ€๋˜์—ˆ์œผ๋ฉด ํ•˜๋Š” ๋” ๋งŽ์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ƒ๊ฐํ•ด๋‚ผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ์™€ โ€‹โ€‹๊ฐ™์ด API๋Š” ํ•ด์•ผ ํ•  ์ผ์„ ์ •ํ™•ํžˆ ์ˆ˜ํ–‰ํ•˜๋ฉฐ ํฌ๋Ÿฌํ”„ํŠธ๊ฐ€ ๊ฑฐ์˜ ๋˜๋Š” ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ๋ณด๋Š” ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ KISS์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์š”์ฒญ์„ ๋งŒ๋“ค๊ณ  ์‘๋‹ต์„ ์‰ฝ๊ณ  ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋งŒ๋“œ๋Š” ํ›Œ๋ฅญํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ด‘๊ณ ๋œ ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ€ํ‹ฐํŒŒํŠธ ์ธ์ฝ”๋”ฉ์„ ๊ด‘๊ณ ํ•˜๊ณ  ๋ฌธ์„œํ™”๋œ ๋””์ž์ธ์„ ํ†ตํ•ด ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์–ด์ƒ‰ํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฌธ์„œํ™”๋˜์–ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

_(...) ๋ˆ„๊ตฐ๊ฐ€๋Š” json ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋‹ค๊ณ  ๋ถˆํ‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค_

json์ด multipart ๋ฏธ๋””์–ด ์œ ํ˜•( httpbis draft 21 )์ด ์•„๋‹Œ multipart application ๋ฏธ๋””์–ด ์œ ํ˜•( rfc4627 )์˜ ํ•˜์œ„ ์œ ํ˜•์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Ÿฌํ•œ ๋ถˆํ‰์— ๋Œ€ํ•œ ๊ทผ๊ฑฐ๋Š” ์—†์Šต๋‹ˆ๋‹ค.

_์–ด๋ ค์›Œ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(...)_

์–ด์ƒ‰ํ•œ ๋ฐ˜๋ฉด์— ์žˆ์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

์ด์ „ ์˜๊ฒฌ์„ ์ฝ์€ ํ›„ ๋‚ด ์ž…์žฅ์„ ๋ฐ˜๋ณตํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. multipart/form-data ๋Š” ํ˜„์žฌ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋‹ค์ค‘ ๋ถ€๋ถ„ MIME ์œ ํ˜•์ด๋ฉฐ(์ธ์šฉ ํ•„์š” :)) ์ด๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ํฐ ์ƒ๋žต์ž…๋‹ˆ๋‹ค.

@piotr-dobrogost: ์œ„์—์„œ ๋งํ•œ ๊ฒƒ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ๋‚˜๋Š” ๋‹น์‹ ์ด ์•ฝ๊ฐ„ ์„ค๋“๋ ฅ ์žˆ๊ฒŒ ์ฃผ์žฅํ•œ ์ฃผ์žฅ์„ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

์š”์ฒญ์€ MIME ์œ ํ˜•์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ด€์ ์€ ์œ„์˜ ๋‘ ์˜๊ฒฌ์„ ์ด์ƒํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด JSON ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๋ถˆ๋งŒ์€ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋กœ๋“œํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ผ๋ฐ˜์ ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ํŒŒ์ผ์ด ์•„๋‹Œ ๋ฉ€ํ‹ฐํŒŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋กœ๋“œํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์š”์ฒญ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋” ์ผ๋ฐ˜์ ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. '์šฐ๋ฆฌ๋Š” multipart ์˜ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ์˜ ํ•˜์œ„ ์œ ํ˜•๋งŒ 'ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ œ๊ณตํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ฃผ์žฅํ•˜๋Š” ๊ฒƒ์€ ์ด์ƒํ•œ ๋ง์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋ฌธ์ œ์˜ ํ•ต์‹ฌ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. API๋Š” ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์š”์ ์ž…๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” _์•„๋ฆ„๋‹ค์šด_ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด๋‚ด์ง€ ๋ชปํ•œ๋‹ค๋ฉด ๊ทธ๋Ÿฐ ์ผ์€ ์ผ์–ด๋‚˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋ถˆํ‰์— ๋Œ€ํ•œ ๊ทผ๊ฑฐ๊ฐ€ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค [์›๋ฌธ ๊ทธ๋Œ€๋กœ]

@piotr-dobrogost ๋‹น์‹ ์€ ๋‚˜๋ณด๋‹ค ๊ฐœ๋ฐœ์ž์˜ ๋ฏธ๋ž˜์— ๋Œ€ํ•ด ๋” ๋งŽ์€ ํฌ๋ง์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์™ธ์—๋Š” ์š”์ฒญํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ •ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. form_data ๋ณด๋‹ค multipart form_data ์™€ ๊ฐ™์€ ์ด๋ฆ„์œผ๋กœ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„์‹œ๋‹ค์‹œํ”ผ (๊ฐ„์ ‘์ ์ด์ง€๋งŒ) multipart ๋Š” ๋‹ค์–‘ํ•œ ๋ฏธ๋””์–ด ์œ ํ˜•์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด์ƒ‰ํ•œ ๋ฐ˜๋ฉด์— ์žˆ์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ฒƒ์ด ์šฐ์•„ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค(ํŒŒ์ด์ฌ์—์„œ๋„).

๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์„ ์ง€์ง€ํ•˜์ง€ ์•Š๋Š”๋‹ค.

ํ•˜์ง€๋งŒ ์ง€์›๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ ์™ธ์—, ์šฐ๋ฆฌ๊ฐ€ data ์— ๋Œ€ํ•ด application/x-www-form-urlencoded , files (๋˜๋Š” files+data )์— ๋Œ€ํ•œ multipart/form-data , ์™œ ์šฐ๋ฆฌ๋Š” ๋˜ ๋‹ค๋ฅธ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ํ•„์š”๋กœ ํ•˜๋Š”๊ฐ€ ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๊ฒƒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๋•Œ ๋‹จ์ง€ multipart/form-data ๋ฅผ ์œ„ํ•ด?

์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด data ๋ฐ files ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ํŒŒ์ผ ์—†์ด requests.post('http://example.com/', files=[('key1', 'param1'), ('key2', 'param2')]) ์™€ ์œ ์‚ฌํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ •ํ™•ํžˆ ๋งํ•˜๋ฉด form_data ๊ฐ€ ์™„์ „ํžˆ ๋ช…ํ™•ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ multipart_form_data ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๊ทธ๊ฒƒ์€ ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค. ์˜ˆ, PEP 8์€ ๋ช…์‹œ์ ์œผ๋กœ ์š”๊ตฌํ•˜์ง€๋งŒ ๊ธฐ์กด ๋™์ž‘์€ ์ž˜ ๋ฌธ์„œํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. @kennethreitz ๊ฐ€ ์ด ๊ธฐ๋Šฅ ์š”์ฒญ์„ ์ˆ˜๋ฝํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•œ ๊ฒฝ์šฐ ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํŒŒ์ผ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋ณ„์นญ์œผ๋กœ ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋™์ž‘์ด ์ด๋ฏธ ์ง€์›๋˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๋ฉด ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@sigmavirus24 ์™€ @Lukasa๋Š” ์ด๊ฒƒ์„ ์™„๋ฒฝํ•˜๊ฒŒ ์š”์•ฝํ–ˆ์Šต๋‹ˆ๋‹ค.

@piotr-dobrogost ๊ท€ํ•˜์˜ ๊ธฐ์—ฌ๋Š” ๋†’์ด ํ‰๊ฐ€๋˜์ง€๋งŒ ๊ท€ํ•˜์˜ ์–ด์กฐ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์™€ ๋ชฉํ‘œ์— ๋Œ€ํ•ด ํ™•๊ณ ํ•œ ์ฃผ์žฅ์„ ํ•˜๋Š” ๊ฒƒ์„ ์ค‘๋‹จํ•˜์‹ญ์‹œ์˜ค.

๋‚ด ๊ด€์ ์—์„œ๋Š” ์š”์ฒญ์ด ์ด๋ฏธ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ฒŒ์‹œ๋ฌผ์„ ์ง€์›ํ•˜์ง€๋งŒ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์ด ์ƒ๋‹นํžˆ ์‹ค๋ง์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. @sigmavirus24 ์˜ ํŒŒ์ผ์„ ๊ฑฐ๊ธฐ์—

๋‚˜๋Š” ์ด๊ฒƒ์ด ์•ž์œผ๋กœ๋„ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ๊ณ„์†ํ•ด์„œ ๋ฌธ์ œ๊ฐ€ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š”๋ฐ, ์™œ ์ด๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋ ค๋Š” ๋…ธ๋ ฅ์ด ์—†๋Š” ๊ฒƒ ๊ฐ™์•„ ์กฐ๊ธˆ ํ˜ผ๋ž€์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

#935์— ๋Œ€ํ•œ ๋‚ด ์‘๋‹ต ๋ณด๊ธฐ

์˜ค ๊ฐ์‚ฌ. ๊ธฐ๋Œ€๋ฉ๋‹ˆ๋‹ค!

@๋ฃจ์นด์‚ฌ

_Requests๋Š” MIME ์œ ํ˜•์„ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค._

multipart/form-data ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค.

_(...) JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋กœ๋“œํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค(...)_

json์„ ๋ณด๋‚ด๋Š” ๊ฒƒ๊ณผ multipart/form-data ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ์„ ๋น„๊ตํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. json์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์€ ์‰ฝ์Šต๋‹ˆ๋‹ค. Content-type ์„ค์ •ํ•˜๊ณ  ๋‚ด์žฅ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ์ค„๋กœ ์ธ์ฝ”๋”ฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. multipart/form-data ๋ณด๋‚ด๋Š” ๊ฒƒ์€ ์š”์ฒญ์˜ ๋ณธ๋ฌธ์ด ํŠน์ • ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ ธ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, json์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์€ HTTP์— ๊ด€ํ•œ ํ•œ ํˆฌ๋ช…ํ•˜์ง€๋งŒ multipart/form-data ๋ณด๋‚ด๋Š” ๊ฒƒ์€ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Requests๋Š” HTTP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋ฏ€๋กœ ๊ทธ๋Ÿฌํ•œ ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

_์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ์•„๋ฆ„๋‹ค์šด ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด๋‚ด์ง€ ๋ชปํ•˜๋ฉด ์ผ์–ด๋‚˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค._

ํŒŒ์ผ๊ณผ ์•„๋ฌด ๊ด€๋ จ์ด ์—†๋Š” multipart/form-data ๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด ํ˜„์žฌ files ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์€ ์–ด๋–ค ์‹์œผ๋กœ๋“  ์•„๋ฆ„๋‹ต์ง€ ์•Š์ง€๋งŒ(์ถ”์•…ํ•ฉ๋‹ˆ๋‹ค), ์–ด๋–ป๊ฒŒ๋“  ์ฝ”๋“œ๋ฒ ์ด์Šค์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. :). ๋œ ์ถ”ํ•œ ๊ฒƒ์„ ์ƒ๊ฐํ•ด๋‚ด๋Š” ๊ฒƒ์€ ์ •๋ง ์‰ฝ์Šต๋‹ˆ๋‹ค :)

@sigmavirus24

_(...) ๊ทธ๋Ÿฌ๋‚˜ ๊ธฐ์กด ๋™์ž‘์€ ์ž˜ ๋ฌธ์„œํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค._

์•„๋ฌด๋ฆฌ ๋งŽ์€ ๋ฌธ์„œ๋„ ๋‚˜์œ API์—์„œ ์ข‹์€ API๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. API๊ฐ€ ์ข‹์„์ˆ˜๋ก ๋ฌธ์„œ๊ฐ€ ๋œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

_(...)_์™€ ์œ ์‚ฌํ•œ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งž์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ๋งค์šฐ ์˜คํ•ด์˜ ์†Œ์ง€๊ฐ€ ์žˆ๊ณ  ์ง๊ด€์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด์ „ ๋Œ“๊ธ€์—์„œ files param์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ž˜๋ชป๋œ ์ ์„ ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก : ๋” ๋‚˜์€ ๊ฒƒ์„ ์ƒ๊ฐํ•ด๋‚ด๋ ค๋ฉด ํ˜„์žฌ API๊ฐ€ multipart/form-data ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จํ•˜์—ฌ ๋‚˜์˜๋‹ค๋Š” ๊ฒƒ์„ ์ธ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@์ŠคํŽ˜์ด์Šค์ผ€์ด์Šค

_๋‚ด ๊ด€์ ์—์„œ๋Š” ์š”์ฒญ์ด ์ด๋ฏธ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ ๊ฒŒ์‹œ๋ฌผ์„ ์ง€์›ํ•˜์ง€๋งŒ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์ด ์ƒ๋‹นํžˆ ์‹ค๋ง์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค._

๋™์˜ํ•˜๋ฉฐ ์ด๊ฒƒ์ด ๋ฌธ์ œ #935๋ฅผ ๋งŒ๋“  ์ด์œ ์ž…๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

@kennethreitz๋ฅผ ์šฉ์„œํ•˜์„ธ์š” @spacecase ์ €๋Š” ์ด ์˜ˆ์ œ์—์„œ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹น์‹ ์ด ์›ํ•˜๋Š” ๊ฒƒ์„ ์ •ํ™•ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ํŒŒ์ผ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด open('filename') ๋ณด์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@sigmavirus24 , ๋ถˆํ–‰ํžˆ๋„ ๊ทธ๊ฒƒ์€ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํŒŒ์ผ์—์„œ ์ฝ๊ณ  ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์— ์•Œ๋ ค์ฃผ๋Š” ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์˜ˆ์—์„œ ๊ฒŒ์‹œ๋ฌผ ๋ณธ๋ฌธ์€

Content-Disposition: form-data; name="key1"; filename="key1"
Content-Type: application/octet-stream

param1
--2f8732ee35564115a6c6e0c1032773e8
Content-Disposition: form-data; name="key2"; filename="key2"
Content-Type: application/octet-stream

param2
--2f8732ee35564115a6c6e0c1032773e8--

filename= ์˜ ์‚ฌ์šฉ์— ์ฃผ์˜ํ•˜์‹ญ์‹œ์˜ค. ์„œ๋ฒ„์— ํŒŒ์ผ์ด ์ „์†ก๋˜๊ณ  ์žˆ์Œ์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ์›น ์•ฑ์—์„œ ์ด ์ž˜๋ชป๋œ ๋™์ž‘์œผ๋กœ ์ž‘์—…ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ฏธ์•ˆํ•˜์ง€๋งŒ, ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ๊ทธ๊ฒƒ์ด๋ผ๊ณ  ๋งํ•˜๋Š” ๋‹น์‹ ์ด ๋„ˆ๋ฌด ์ฃผ์ œ๋„˜๊ฒŒ ๋งํ•˜๋Š” ๊ฒƒ์€ ๋‚˜๋ฅผ ํ™”๋‚˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์•„์ด๋””์–ด์™€ ๋„์›€์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์™”์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹น์‹ ์€ ์ด ๊ฒฝ์šฐ ๋‘˜ ๋‹ค ์›ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค๋งŒ, ์ €๋ฅผ ์–•์žก์•„๋ณด๊ฒŒ ํ•˜์ง€ ๋ง์•„์ฃผ์„ธ์š”.

ํ , ํ–‰๋™์„ ์ž˜๋ชป ๊ธฐ์–ตํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ฏธ์•ˆํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์„ ํ™”๋‚˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ๋ง์„ ๊ฑฐ๋Š” ๊ธฐ๋ถ„์ด ๋“ค๊ฒŒ ํ•˜๋ ค๋Š” ์˜๋„๋Š” ์ „ํ˜€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. multipart/form-data ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค๋Š” ์ ์— ๋™์˜ํ•˜์ง€๋งŒ API์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ์ „ํ˜€ ์šฐ์•„ํ•˜์ง€ ์•Š๋‹ค๋Š” ์ ์—๋Š” ์—ฌ์ „ํžˆ ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@spacecase #935์— ๋Œ€ํ•œ ์ œ ๋‹ต๋ณ€์„ ์ฐธ์กฐํ•˜์„ธ์š”. ์ƒํ™ฉ์ด ๋‚˜์•„์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ํ”ผ๋“œ๋ฐฑ์€ ์ค‘์š”ํ•˜๊ณ  ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. :)

@spacecase ๋Š” ๊ท€ํ•˜์˜ ์˜๊ฒฌ์ด ์ค‘์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๋Š” ์ œ์Šค์ฒ˜๋กœ, Content-Type ํ—ค๋”๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•˜์ง€๋งŒ ์ด๋Š” ์•ฝ๊ฐ„์˜ ์„ฑ๊ฐ€์‹ฌ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@sigmavirus24 ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์‹œ๋„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํŠธ๋ฆญ์„ ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋‹น์‹ ์ด ๋‚˜๋ฅผ ํ™”๋‚˜๊ฒŒ ํ•  ์˜๋„๊ฐ€ ์•„๋‹ˆ์—ˆ๋‹ค๋Š” ์ ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๊ธฐ๋ถ„์ด ์ข‹์•„์ง€๊ณ  ๋‹น์‹ ์ด๋‚˜ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ์•„๋ฌด ๊ฒƒ๋„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋„ค, ์ œ๊ฐ€ ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋Š” ๋ป”๋ป”ํ•˜๊ฒŒ ๋“ค๋ฆฌ๋Š” ๊ฒƒ ๊ฐ™์•„์„œ ์ธํ„ฐ๋„ท์— ์“ฐ๋Š” ๊ฒƒ์„ ๋‹ค๋“ฌ์–ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์•„์š”. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๋„ ๋‚˜์™€ ๋™์˜ํ–ˆ์ง€๋งŒ ๋‚˜๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‚ด ์˜๋„ ์—†์ด ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋ถˆ์พŒ๊ฐ์„ ์ฃผ๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ๊นจ๋‹ซ๊ธฐ์— ์ถฉ๋ถ„ํžˆ ํฐ ํ‘œ๋ณธ ํฌ๊ธฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ฒŒ์‹œํ•  ํŒŒ์ผ๊ณผ ๋ช‡ ๊ฐ€์ง€ ํ‚ค-๊ฐ’์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋Ÿฌํ•œ mutilpart-form ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๋‹น์‹ ์ด ๋‚˜๋ฅผ ๋„์šธ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

Content-Disposition: form-data; name="up"; filename="aa.PNG"
Content-Type: image/png

file data
---------------------------7dee5302248e
Content-Disposition: form-data; name="exp"


-----------------------------7dee5302248e
Content-Disposition: form-data; name="ptext"

text
-----------------------------7dee5302248e
Content-Disposition: form-data; name="board"

DV_Studio
-----------------------------7dee5302248e--

I tried this way but only got a 504 error.
myfile=[('file',open('bb.jpg')),('exp','python'),('ptext',''),('board','DV_Studio')]
r = requests.post(url,files=myfile)

@deerstalker์— ๋Œ€ํ•œ ์งˆ๋ฌธ์€ StackOverflow ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ๊ท€ํ•˜์˜ ์งˆ๋ฌธ์— ๋‹ตํ•˜๊ธฐ ์œ„ํ•ด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ๊ฐ€ ์ง„ํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. sigmavirus24/requests-toolbelt

๋˜ํ•œ ์—ฌ๊ธฐ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ์ด์ „์— StackOverflow์—์„œ ์ด ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•œ ์ ์ด

ํŒŒ์ผ ์—†์ด ๋ฉ€ํ‹ฐํŒŒํŠธ ๊ฒŒ์‹œ๋ฌผ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ๋กœ์„œ๋Š” requests.post(url, data=data_dict) ๋˜๋Š” requests.post(url, data=data_dict, files={}) ๋ฅผ ์ˆ˜ํ–‰ํ•ด๋„ ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ files ํ‚ค์›Œ๋“œ์˜ ๊ธฐ๋ณธ๊ฐ’์€ None ์ด๋ฏ€๋กœ ๋‘ ๊ฐ€์ง€ ๊ณ ์œ ํ•œ ๋™์ž‘์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. multipart/form-data files={} ์ง€์ •๋˜๋ฉฐ, application/x-www-form-urlencoded ํ•˜์ง€ ์•Š์„ ๋•Œ.

๋‚ด๊ฐ€ ๋ญ ๋†“์นœ ๊ฑฐ ์—†๋‹ˆ?

@jwoillez ์ œ๊ฐ€ ๊ฒŒ์‹œํ•œ ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ ๋งํฌ๋ฅผ ํŒ”๋กœ์šฐํ•˜์…จ๋‚˜์š”?

๋‚˜๋Š” ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜์ง€๋งŒ ๊ฑฐ๊ธฐ์— ๋Œ€ํ•œ ๊ท€ํ•˜์˜ ๋‹ต๋ณ€์€ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ Multipart POST๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ์›๋ž˜ ๋ฌธ์ œ์ธ Multipart POST with no file๋กœ ๋Œ์•„๊ฐ”์Šต๋‹ˆ๋‹ค.

ํŒŒ์ผ ๊ฐ์ฒด๋Š” ๋ฌธ์ž์—ด์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. =) ์›ํ•˜๋Š” ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚ด๊ฐ€ ๋‹น์‹ ์˜ ์ œ์•ˆ์„ ๋”ฐ๋ฅธ๋‹ค๋ฉด ๋‚˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋‚ณ์ง€ ์•Š์„๊นŒ์š”?

Content-Disposition: form-data; name="file"; filename="filename.txt"
Content-Type: text/plain

content
--3eeaadbfda0441b8be821bbed2962e4d--

์—ฌ๊ธฐ์„œ content ๋Š” ํŒŒ์ผ ๋Œ€์‹  ์‚ฌ์šฉํ•˜๋„๋ก ์ดˆ๋Œ€ํ•œ ๋ฌธ์ž์—ด์ž…๋‹ˆ๊นŒ?

๋‚˜๋Š” ์ •๋ง๋กœ ์ด๊ฒƒ๋งŒ ์ซ“๊ณ  ์žˆ๋‹ค:

Content-Disposition: form-data; name="key1"

value1
--3eeaadbfda0441b8be821bbed2962e4d

์›ํ•˜์ง€ ์•Š๋Š” ํŠœํ”Œ์˜ ํ•„๋“œ๋Š” ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋‚จ๊ฒจ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

files = {'name': ('', 'content')}

์•ž์œผ๋กœ๋Š” StackOverflow๋กœ ์งˆ๋ฌธ์„ ๋ณด๋‚ด์ฃผ์„ธ์š”. ๋ชจ๋“  ์œ ์ง€ ๊ด€๋ฆฌ์ž๋Š” ์ •๊ธฐ์ ์œผ๋กœ ์ด๋ฅผ ์ถ”์ ํ•˜๋ฉฐ ์ด๋Ÿฌํ•œ ์งˆ๋ฌธ์„ ํ•˜๊ธฐ์— ๋” ์ ์ ˆํ•œ ๊ณณ์ž…๋‹ˆ๋‹ค.

์ฐพ๋˜ ๋‹ต๋ณ€์ด๋„ค์š” ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์†Œ์Œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰ ์งˆ๋ฌธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(๋นˆ ํŒŒ์ผ ์ด๋ฆ„, ๋นˆ ์ฝ˜ํ…์ธ  ์ง€์ •)?

Content-Disposition: form-data; name="file"; filename=""
Content-Type: text/plain


--3eeaadbfda0441b8be821bbed2962e4d--

ํŠœํ”Œ์˜ ์ฝ˜ํ…์ธ  ์„น์…˜์— ๋นˆ ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๋นˆ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ž ๊ทธ๋Œ€๋กœ ๋นˆ ํŒŒ์ผ ์ด๋ฆ„์„ ์ œ๊ณตํ•  ์ˆ˜ ์—†์ง€๋งŒ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŒŒ์ผ ์ด๋ฆ„์€ ์ •ํ™•ํžˆ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ด์ƒํ•œ ์ด์œ ๋กœ ๋•Œ๋•Œ๋กœ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.
์ด ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ API๋ฅผ ๊ฐ•ํ™”ํ•˜๋ ค๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์—๊ฒŒ ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

class ForceMultipartDict(dict):
    def __bool__(self):
        return True


FORCE_MULTIPART = ForceMultipartDict()  # An empty dict that boolean-evaluates as `True`.


client.post("/", data={"some": "data"}, files=FORCE_MULTIPART)

๋˜๋Š” ๋„๊ตฌ ๋ฒจํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํ•ดํ‚น์— ์˜์กดํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰