2012-04-08 79 views
5

我試圖從一個appengine應用程序發送一個多部分發布請求到一個外部(django)api託管在dotcloud上。該請求包括一些文本和文件(PDF),並使用下面的代碼appendine python中的multipart/form-data發佈請求不起作用

from google.appengine.api import urlfetch 
from poster.encode import multipart_encode 
from libs.poster.streaminghttp import register_openers 

register_openers() 
file_data = self.request.POST['file_to_upload'] 
the_file = file_data 
send_url = "http://127.0.0.1:8000/" 
values = { 
      'user_id' : '12341234', 
      'the_file' : the_file 
      } 

data, headers = multipart_encode(values) 
headers['User-Agent'] = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' 
data = str().join(data) 
result = urlfetch.fetch(url=send_url, payload=data, method=urlfetch.POST, headers=headers) 
logging.info(result.content) 

當此方法運行的AppEngine提供了以下警告發送(我不知道它是否與我的問題)

Stripped prohibited headers from URLFetch request: ['Content-Length'] 

而且Django的通過以下錯誤

<class 'django.utils.datastructures.MultiValueDictKeyError'>"Key 'the_file' not found in <MultiValueDict: {}>" 

Django的代碼將是非常簡單的,當我使用郵遞員Chrome擴展程序發送一個文件工作。

@csrf_exempt 
def index(request): 
    try: 
     user_id = request.POST["user_id"] 
     the_file = request.FILES["the_file"] 
     return HttpResponse("OK") 
    except: 
     return HttpResponse(sys.exc_info()) 

如果我添加

print request.POST.keys() 

我得到含USER_ID和the_file表明該文件不被髮送的文件的字典。如果我對文件做同樣的處理,即

print request.FILES.keys()  

我得到了空的列表[]。

編輯1:

我已經改變了我的問題,以實現someone1的建議,但是這仍然不能解決。我還加入了由Glenn發送的鏈接推薦的標題,但沒有喜悅。

編輯2:

我也試着發送the_file作爲

the_file = file_data.file 
the_file = file_data.file.read() 

變化,但我得到了同樣的錯誤。

編輯3:

我也試着編輯我的Django應用

the_file = request.POST["the_file"] 

然而,當我嘗試使用

path = default_storage.save(file_location, ContentFile(the_file.read())) 

它失敗

本地保存的文件
<type 'exceptions.AttributeError'>'unicode' object has no attribute 'read'<traceback object at 0x101f10098> 

同樣,如果我嘗試訪問the_file.file(因爲我可以在我的AppEngine應用程式存取),它告訴我

<type 'exceptions.AttributeError'>'unicode' object has no attribute 'file'<traceback object at 0x101f06d40> 

回答

8

這裏是我在本地測試的一些代碼應該做的竅門(我使用了不同於webapp2的處理程序,但試圖將其修改爲webapp2。您還需要在這裏http://atlee.ca/software/poster/發現海報LIB):

在您的文章處理GAE上:

from google.appengine.api import urlfetch 
from poster.encode import multipart_encode 
payload = {} 
payload['test_file'] = self.request.POST['test_file'] 
payload['user_id'] = self.request.POST['user_id'] 
to_post = multipart_encode(payload) 
send_url = "http://127.0.0.1:8000/" 
result = urlfetch.fetch(url=send_url, payload="".join(to_post[0]), method=urlfetch.POST, headers=to_post[1]) 
logging.info(result.content) 

確保你的HTML表單包含method="POST" enctype="multipart/form-data"。希望這可以幫助!

編輯: 我嘗試使用webapp2的處理程序,實現了文件的放送方式比框架我如何使用作品(KAY)來測試不同。這裏是更新的代碼,應該做的(生產測試):

import webapp2 
from google.appengine.api import urlfetch 
from poster.encode import multipart_encode, MultipartParam 

class UploadTest(webapp2.RequestHandler): 
    def post(self): 
    payload = {} 
    file_data = self.request.POST['test_file'] 
    payload['test_file'] = MultipartParam('test_file', filename=file_data.filename, 
              filetype=file_data.type, 
              fileobj=file_data.file) 
    payload['name'] = self.request.POST['name'] 
    data,headers= multipart_encode(payload) 
    send_url = "http://127.0.0.1:8000/" 
    t = urlfetch.fetch(url=send_url, payload="".join(data), method=urlfetch.POST, headers=headers) 
    self.response.headers['Content-Type'] = 'text/plain' 
    self.response.out.write(t.content) 
    def get(self): 
    self.response.out.write(""" 
    <html> 
     <head> 
      <title>File Upload Test</title> 
     </head> 
     <body> 
      <form action="" method="POST" enctype="multipart/form-data"> 
       <input type="text" name="name" /> 
       <input type="file" name="test_file" /> 
       <input type="submit" value="Submit" /> 
      </form> 
     </body> 
    </html>""") 
+0

嗨,感謝您的代碼。此處提交的appengine中存在一個錯誤(http://code.google.com/p/googleappengine/issues/detail?id=627),這會限制multipart_encode方法的實用性。我現在只是測試一個解決方法。 – user714852 2012-04-16 19:39:56

+0

我不完全確定這個錯誤會影響你正在努力完成的任務。事實上,我不知道這個bug是否仍然有效,因爲你可以對數據進行編碼並將其作爲POST urlfetch中的有效載荷進行打包,就像我使用海報庫給出的示例代碼一樣。 – someone1 2012-04-17 16:01:35

+0

完美!編輯後的版本完全按照要求工作 - 非常感謝您的幫助,這讓我分心! – user714852 2012-04-17 17:05:08