# [Flask]Request & Response ###### tags: `python` `flask` 在HTTP協議中,使用requests傳送請求,常見的做法有傳送GET或POST,而這邊要討論較容易發生問題的POST。 > POST提交的資料必須放在訊息主體中,但是協議中並沒有規定必須使用什麼編碼方式,從而導致提交方式的不同。服務端根據請求頭中的Content-Type欄位來獲知請求中的訊息主體是用何種方式進行編碼,再對訊息主體進行解析。 :::warning 單一requests只能依協議選擇其中一種Content-Type ::: ## Content-Type ### application/x-www-form-urlencoded 以form表單形式提交資料,一般存在於網站的登入,用來提交使用者名稱和密碼。以http://httpbin.org/post 為例,在requests中,以form表單形式傳送post請求,只需要將請求的引數構造成一個字典,然後傳給requests.post()的data引數即可。 ```Python url = 'http://httpbin.org/post' d = {'key1': 'value1', 'key2': 'value2'} r = requests.post(url, data=d) print(r.text) ``` ### application/json 以json串提交資料,主要是用於傳送ajax請求中,動態載入資料。 * 傳送資料前,需要把data進行json編碼。 ```Python r = requests.post(url=url, data=json.dumps(data), headers=headers) ``` * requests還提供了一個json引數,自動使用json方式傳送,而且在請求頭中也不用顯示宣告’Content-Type’:’application/json; charset=UTF-8’ ```Python r = requests.post(url=url, json=data, headers=headers) ``` ### multipart/form-data 上傳檔案以multipart形式傳送post請求,只需將一檔案傳給requests.post()的files引數即可。 ```Python url = 'http://httpbin.org/post' files = {'file': open('upload.txt', 'rb')} r = requests.post(url, files=files) print(r.text) ``` ## 同時傳送JSON & FILE 由於只能指定一個Content-Type,所以必須將資料包在一起,並各別指定資料型態,最後由pyrequests決定整個的Content-Type。 * Request ```Python data = {"param_1": "value_1", "param_2": "value_2"} files = { 'json': (None, json.dumps(data, ensure_ascii=False).encode('utf-8'), 'application/json'), 'file': (os.path.basename(filename), open(filename, 'rb'), 'application/octet-stream') } r = requests.post(url, files=files) print(r.text) ``` * Response ```Python # 取得json data = json.loads(request.form['json']) data = data['domain'] # 取得file cur_file = request.files['file'] filename = cur_file.filename cur_file.save(filename) text_arr = [] with codecs.open(filename, "r", "utf-8") as fp: for line in fp.readlines(): text_arr.append(line.strip()) ``` ## 參考 [Python requests傳送post請求的一些疑點](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/356689/)