我试图从appengine应用程序向dotcloud上托管的外部(django)api发送多部分帖子请求。该请求包括一些文本和文件(pdf),并使用以下代码发送
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代码非常简单,当我使用postman 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的字典,表明该文件没有作为文件发送。如果我为FILES做同样的事情,那就是
print request.FILES.keys()
我得到空列表[]。
我已经改变了我的问题以实施某人的建议1但是这仍然失败了。我还包括Glenn发送链接推荐的标题,但没有欢乐。
我还尝试将the_file作为
的变体发送the_file = file_data.file
the_file = file_data.file.read()
但我得到同样的错误。
我还尝试编辑我的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>
答案 0 :(得分:9)
这是我在本地测试的一些代码应该做的伎俩(我使用了与webapp2不同的处理程序,但尝试将其修改为webapp2。你还需要在这里找到的海报lib http://atlee.ca/software/poster/):
在GAE的POST处理程序中:
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>""")
答案 1 :(得分:2)
您正在对要对其进行multipart_encoding的数据进行urlencoding。看看这个:Trying to post multipart form data in python, won't post