51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Python 调用接口进行文件上传的踩坑记录

postman 接口调用 {#postman-接口调用}

一般文件上传的接口大概如下,某个字段需要上传文件,比如这里的是file字段

正常请求 {#正常请求}

一般情况下,使用下面的代码就可以正常调通接口,这种方式也是 postman 里面自动生成的代码的方式。

import requests

headers = {
'xxx': 'xxx',
'xxx': 'xxx',
}


host = 'http://xx.xx.xx.xx:xxxx'


def upload_file(data, filename, content):
api = '/api/v1/objectStore/bucket/{}/object'.format('bug')
url = host + api
files = [('file', (filename, content, 'text/plain'))]
resp = requests.put(url, headers=headers, data=data, files=files)
print(resp.status_code, resp.text)

if` `name` `==` `'main':`
`name` `=` `'中文.docs'`
`d` `=` `{'objectName':` `name}`
`with` `open('Info.txt',` `'rb')` `as` `f:`
`ctx` `=` `f.read()`
`upload_file(d,` `'中文.txt',` `ctx)`
`

返回也OK:

(200, u'{"code":0,"codeExplain":"","error":"","data":{"objectName":"\u4e2d\u6587.docs"}}')

报错处理方式 {#报错处理方式}

但是也有时候上面的方式会报错,比如 python2 的情况下(我遇到过的更离谱,同样py2在Windows不报错,在Linux报错),一般报错是因为文件名称包含中文导致的报错,处理方式有两种,具体如下。

urllib3 的方式 {#urllib3-的方式}

此方式只需要使用内置的 urllib3 模块

from urllib3 import encode_multipart_formdata

import requests


headers = {}


def upload_file(data, filename, content):
api = '/api/v1/objectStore/bucket/{}/object'.format('bug')
url = host + api


    <span class="c1"># 特殊处理</span>
    <span class="n">data</span><span class="p">[</span><span class="s1">'file'</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
    <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">[</span><span class="s1">'Content-Type'</span><span class="p">]</span> <span class="o">=</span> <span class="n">encode_multipart_formdata</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>

    <span class="n">resp</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">data</span><span class="p">)</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">status_code</span><span class="p">,</span> <span class="n">resp</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>




MultipartEncoder 方式 {#multipartencoder-方式}

此方式需要安装第三方库 requests_toolbelt

import urllib
import requests
from requests_toolbelt import MultipartEncoder

headers = {}


def upload_file(data, filename, content):
api = '/api/v1/objectStore/bucket/{}/object'.format('bug')
url = host + api


    <span class="c1"># 特殊处理</span>
    <span class="n">encoded_name</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">quote</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
    <span class="n">data</span><span class="p">[</span><span class="s1">'file'</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">encoded_name</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">MultipartEncoder</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
    <span class="n">decoded_m</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">to_string</span><span class="p">()</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">decoded_m</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">encoded_name</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
    <span class="n">headers</span><span class="p">[</span><span class="s1">'Content-Type'</span><span class="p">]</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">content_type</span>

    <span class="n">resp</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">data</span><span class="p">)</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">resp</span><span class="o">.</span><span class="n">status_code</span><span class="p">,</span> <span class="n">resp</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>




偷懒方式--随便取个名 {#偷懒方式-随便取个名}

还有一种方式更简单,因为报错是因为文件名包含中文,而一般file里面的文件名并不是接口真的要用的(接口一般会让你单独使用一个字段传文件名,比如上面接口的objectName字段),所以,其实可以直接随便写个非中文的名称就行,比如:

# 只需要改这一行
files = [('file', (filename, content, 'text/plain'))]
# 改成下面
files = [('file', ('a', content, 'text/plain'))]

警告

但是这种方式并不是总有效,也要分接口的,所以可以先试用这个方式,不行再换上面的方式

赞(0)
未经允许不得转载:工具盒子 » Python 调用接口进行文件上传的踩坑记录