应用引擎提交multipart/form-data表单时编码问题

13 投票
6 回答
2387 浏览
提问于 2025-04-16 03:37

我有一个简单的表单,用来提交图片和图片的标题。这个在我本地的开发服务器上运行得很好,但当我把代码部署到线上时,标题中的非 ASCII 字母就变得乱码了,出现了一些 ASCII 和十六进制的混合情况。比如 Ísland 就变成了 =CDsland。值得注意的是,我在头部的第一行使用了 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 来设置字符编码。而且 utf-8 对我其他的表单都有效,只有这个多部分表单出现了乱码。总之,这就是我的表单:

<form action="{{ uploadurl }}" enctype="multipart/form-data" method="post">
  <div><label>Title</label><input type="text" name="title" class="string" /></div>
  <div><label>Picture</label><input type="file" name="img"/></div>
  <div style="margin-top:10px;"><input type="submit" value="Add picture" /></div>
  <input type="hidden" value="{{ album.key }}" name="alid"/>
</form>

这是处理这个表单的类:

# handler for posting photos
class PostPhoto(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload_files =  self.get_uploads('img')
        photourl = images.get_serving_url(str(upload_files[0].key()))
        photo = Photo()
        #because of multipart/form-data
        photo.title = self.request.get("title")
        photo.photourl = photourl
        photo.photoalbum = PhotoAlbum.get(self.request.get('alid'))     
        photo.put()

有没有人知道我该怎么解决这个问题?我需要在服务器端做一些编码或解码吗?我试着在网上搜索这个问题,但没有找到结果(我是 Python 新手),所以这是我最后的办法了,如果再不行我就只能改变设计,把表单拆开了。

6 个回答

2

=CD 是 Í 的 quoted-printable 表示方式。

我不知道为什么生产服务器会给你这个 quoted-printable 格式的数据,而开发服务器却没有。不过,你可以使用标准库中的 quopri 模块来解码它。

5

我在使用Django的非关系型数据库时遇到了一些问题,后来通过这个中间件解决了:

http://code.google.com/p/googleappengine/issues/detail?id=2749#c33

import logging
import quopri
log = logging.getLogger(__name__)

class BlobRedirectFixMiddleware(object):
    def process_request(self, request):
        if request.method == 'POST' and 'HTTP_X_APPENGINE_BLOBUPLOAD' in request.META and request.META['HTTP_X_APPENGINE_BLOBUPLOAD'] == 'true':
            request.POST = request.POST.copy()
            log.info('POST before decoding: %s' % request.POST)
            for key in request.POST:
                if key.startswith('_') or key == u'csrfmiddlewaretoken':
                    continue
                value = request.POST[key]
                if isinstance(value,(str, unicode)):
                    request.POST[key] = unicode(quopri.decodestring(value), 'iso_8859-2')
            log.info('POST after decoding: %s' % request.POST) 
        return None
5

这是一个已知的错误。你可以在这里查看详细信息:http://code.google.com/p/googleappengine/issues/detail?id=3761

要恢复原始数据,你需要做以下几步:

>>> import quopri
>>> t = unicode(quopri.decodestring('=CD'), 'iso_8859-2')
>>> print t
Í

撰写回答