最近接觸到了上傳圖片的API,所以就學(xué)習(xí)如何使用Python上傳圖片等二進(jìn)制文件。
Python自帶的urllib, urllib2庫并不能很好的解決用戶上傳二進(jìn)制文件的問題,因?yàn)閡rlencode方法默認(rèn)采用的encoding是‘application/x-www-form-urlencoded’格式,當(dāng)我們上傳二進(jìn)制文件的時(shí)候需要將其encode成'multipart/form-data'格式,所以只能借助一些python的擴(kuò)展庫了。
這里介紹兩種方法:1. pycurl 2. poster 另外還有一個(gè)urllib2_file,大家Google學(xué)習(xí)吧。 - import pycurl
-
- pc = pycurl.Curl()
- pc.setopt(pycurl.POST, 1) # POST method
- pc.setopt(pycurl.URL, 'http://example.com/webservice/upload/') # 上傳的API接口
- pc.setopt(pycurl.HTTPPOST, [('file1', (c.FORM_FILE, '/path/to/your/imagefile'))]) # 設(shè)置POST方法的參數(shù)
- pc.perform() # Actually do POST request, 文件上傳
- pc.close()
- from poster.encode import multipart_encode
-
from poster.streaminghttp import register_openers
-
import urllib2
-
-
register_openers()
- # datagen: 對POST參數(shù)的encode(multipart/form-data)
- # headers: 發(fā)起POST請求時(shí)的http header的信息
-
datagen, headers = multipart_encode({'file':open('/path/to/imagefile', 'rb')})
- # Create a Request object
-
request = urllib2.Request('http://example.com/webservice/upload/', datagen, headers)
- # Actually do POST request
- response = urllib2.urlopen(request)
- print response.read() # 打印服務(wù)器端的回應(yīng)信息
N.B. 其實(shí)上傳文件的過程就是先收集POST參數(shù)數(shù)據(jù),然后將參數(shù)數(shù)據(jù)進(jìn)行multipart/form-data格式化,這樣創(chuàng)建了一個(gè)請求對象,最后對這個(gè)請求進(jìn)行處理(實(shí)際就是真正的文件上傳操作)。
只有上面的代碼片段,演示的效果肯定還不夠形象生動,下面我們就利用Django來做個(gè)小實(shí)驗(yàn)吧。
假如我們的client端腳本采用了poster的代碼片段,稍作修改如下: - from poster.encode import multipart_encode
-
from poster.streaminghttp import register_openers
-
import urllib2
-
-
register_openers()
-
datagen, headers = multipart_encode({'file':open('/path/to/imagefile', 'rb')})
-
request = urllib2.Request('http://localhost:8000/web/upload/', datagen, headers)
-
- response = urllib2.urlopen(request)
-
-
print response.read()
然后我們在server端配置如下: - Django_Project $> python manage.py startapp web
-
Django_Project $> cd web
- web $> vim urls.py (內(nèi)容見下文)
- web $> vim views.py (內(nèi)容見下文)
web $> cd ..
-
Django_Project $> vim urls.py (內(nèi)容見下文)
N.B. 需要在settings.py文件中的INSTALLED_APP中添加'web'應(yīng)用。 Django_Project.urls.py 內(nèi)容: - from django.conf.urls.defaults import *
-
...
-
urlpatterns = patterns('',
-
...
-
(r'web/', include('web.urls')),
-
...
-
)
Django_Project.web.urls.py 內(nèi)容: - from django.conf.urls.defaults import *
-
-
urlpatterns = patterns('',
-
(r'upload/', 'web.views.upload'),
-
)
Django_Project.web.views.py 內(nèi)容: - # Create your views here.
-
from django.http import HttpResponse
-
from django.views.decorators.csrf import csrf_exempt
-
-
@csrf_exempt # 若沒有csrf處理,服務(wù)器會返回403 forbidden錯(cuò)誤
-
def upload(request):
-
for file_name in request.FILES.keys():
- file_obj = request.FILES[file_name]
- destination = open('/path/to/save/imagefile', 'wb+')
-
for chunk in file_obj.chunks():
- destination.write(chunk)
- destination.close()
-
-
return HttpResponse('All uploaded files have been saved.')
最后運(yùn)行客戶端腳本,成功提示上傳文件已保存,服務(wù)器端會創(chuàng)建用戶上傳的文件。 |