Django 1.1.1 处理 multipart/form-data 时崩溃

1 投票
1 回答
3520 浏览
提问于 2025-04-15 19:46

初始故事

我正在尝试通过一个简单的表单实现文件上传(这里贴的是简化版,但重要的部分都在):

  <form method="POST" action="" enctype="multipart/form-data">
      <input type="file" name="up_file" size="50">
      <input type="hidden" name="cpk" value="{{c.pk}}">
      <input type="submit" name="btn_submit">
  </form>

现在,运行在 wsgi 下的服务器脚本收到了空的 request.FILESrequest.POST字典,所以我决定切换到开发服务器来调试。

令人惊讶的是,当我输入request.POSTrequest.FILES并按下回车时,ipdb 调试器就卡住了……另一方面,当我从标签中去掉enctype="multipart/form-data"时,我可以查看request.POSTrequest.FILES,但当然这时request.FILES是空的。

(另外,去掉enctype="multipart/form-data"似乎也解决了 wsgi 的问题……)

更新

我尝试了 Opera 10 和 Firefox 3.5 的所有组合,enctype="multipart/form-data"和没有 multipart/form-data,以及开发服务器和 mod_wsgi。结果是,enctype="multipart/form-data"导致了问题。所以现在我打算去查看 Django 的 bug 跟踪器,看看这是否是一个已知的问题。

同时,也许这里有人可以给我指个方向。

1 个回答

4

你可能需要提供你的视图和表单代码,因为我们在Django 1.1.1中使用了带有enctype="multipart/form-data"的表单上传,并且效果很好。

下面这个简单的应用程序在开发服务器上运行得非常顺利。

views.py

from django import forms
from django.shortcuts import render_to_response

class UploadForm(forms.Form):
    cpk = forms.CharField(max_length=256)
    f = forms.FileField()

def my_upload_view(request):
    if request.method == 'POST':
        form = UploadForm(request.POST, request.FILES)
        if form.is_valid():
            print "Got cpk",form.cleaned_data['cpk']
            print "Got file",request.FILES['f'].read()
    else:
        form = UploadForm()
    return render_to_response('upload.html', {'form':form})

upload.html

<html>
<body>
    <form enctype="multipart/form-data" method="post">
        {{ form.f }}
        {{ form.cpk }}
        <input type="submit" />
    </form>
</body>
</html>

我使用Django的表单实例来渲染文件输入框,但它生成了一个非常常见的<input type="file" name="f" id="id_f" />

使用这个示例,我可以在开发服务器的终端上看到文件的内容(我测试了一个简单的文本文件)。我可以推荐的一些注意事项和测试方法包括:

  • 确保你上传的文件小于settings.FILE_UPLOAD_MAX_MEMORY_SIZE(默认是2.5 MB)
  • 仔细检查一下你是否定义了任何自定义的文件上传处理程序,这可能会影响上传过程(settings.FILE_UPLOAD_HANDLERS
  • 尝试上传一个非常简单的文件(比如一个小文本文件),看看问题是否依然存在
  • 使用工具检查原始的HTTP请求/响应流量(firebug可以帮你做到这一点,还有一些独立的应用程序可以作为代理来帮助你)……有时候,当你看到原始流量时,解决方案会一下子显现出来。

如果你还没有找到,Django文件上传文档里有很多示例。

撰写回答