appengine python中包含多部分/表单数据的Post请求不起作用

appengine python中包含多部分/表单数据的Post请求不起作用,python,django,google-app-engine,post,Python,Django,Google App Engine,Post,我正试图从appengine应用程序向dotcloud上托管的外部(django)api发送一个多部分post请求。请求包括一些文本和一个文件(pdf),并使用以下代码发送 from google.appengine.api import urlfetch from poster.encode import multipart_encode from libs.poster.streaminghttp import register_openers register_openers() fil

我正试图从appengine应用程序向dotcloud上托管的外部(django)api发送一个多部分post请求。请求包括一些文本和一个文件(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会发出以下警告(我不确定是否与我的问题有关)

Django通过以下错误发送

<class 'django.utils.datastructures.MultiValueDictKeyError'>"Key 'the_file' not found in <MultiValueDict: {}>"
如果我加上

print request.POST.keys()
我得到了一个包含用户\u id和\u文件的字典,表明该文件没有作为文件发送。如果我对文件也这样做,即

print request.FILES.keys()    
我得到一个空列表[]

编辑1: 我已经改变了我的问题,以实施某人的建议,但这仍然失败。我还包括了Glenn发送的链接建议添加的标题,但没有joy

编辑2: 我还尝试将_文件作为

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>
“unicode”对象没有属性“read”
同样,如果我尝试访问_file.file(我可以在appengine应用程序中访问),它会告诉我

<type 'exceptions.AttributeError'>'unicode' object has no attribute 'file'<traceback object at 0x101f06d40>
“unicode”对象没有属性“file”

您正在对数据进行URL编码,而您应该对其进行多部分编码。看看这个:

这里是我在本地测试的一些代码,应该可以做到这一点(我使用了不同于webapp2的处理程序,但试图将其修改为webapp2。您还需要在此处找到海报库):

在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处理程序,并意识到文件的服务方式不同于我使用works(KAY)测试的框架。下面是应该实现这一技巧的更新代码(在生产中测试):

导入webapp2
从google.appengine.api导入urlfetch
从poster.encode导入multipart_encode,MultipartParam
类UploadTest(webapp2.RequestHandler):
def post(自我):
有效载荷={}
file\u data=self.request.POST['test\u file']
有效负载['test_file']=MultipartParam('test_file',filename=file_data.filename,
filetype=file\u data.type,
fileobj=file_data.file)
有效负载['name']=self.request.POST['name']
数据,标题=多部分编码(有效负载)
发送url=”http://127.0.0.1:8000/"
t=urlfetch.fetch(url=send_url,payload=”“.join(数据),method=urlfetch.POST,headers=headers)
self.response.headers['Content-Type']='text/plain'
自我、回应、输出、写入(t.content)
def get(自我):
self.response.out.write(“”)
文件上传测试
""")

您好,谢谢您的代码。appengine field here()中有一个bug,它限制了multipart_encode方法的实用性。我现在只是在测试一个变通方法。我不完全确定这个错误是否会影响到您试图完成的任务。事实上,我不知道这个bug是否仍然有效,因为您可以对数据进行编码,并将其打包为POST urlfetch中的有效负载,就像我使用poster lib.Perfect给出的示例代码一样!编辑后的版本完全按照要求工作-非常感谢您的帮助,这让我分心!
<type 'exceptions.AttributeError'>'unicode' object has no attribute 'file'<traceback object at 0x101f06d40>
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)
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>""")