IIS, Helicon Zoo, Django - сайт загрузки файлов - невозможно загрузить более 2,5 МБ (проблема с чанками)

Последние несколько дней я ломал голову над этим и не смог найти много способов помочь в решении моей конкретной проблемы. Вот мои настройки.

Windows 7
IIS 7.5
Helicon Zoo 3.1.98.508
Django 1.6.3
Python 2.7.3

Должен сказать, что я новичок в зоопарке Джанго и Геликон.

Происходит то, что, хотя у меня, похоже, нет проблем с загрузкой файла со значением по умолчанию, равным 2,5 Мб, я не могу заставить куски загружать правильно для чего-либо сверх этой суммы. Хотя я уверен, что смогу увеличить этот лимит в своем файле настроек, я бы предпочел не делать этого, так как для моей цели я видел необходимость загружать файлы большего размера, чем то, что я действительно хотел бы обрабатывать памятью.

Когда я пытаюсь это сделать, я вижу довольно неинформативную ошибку 500 от Helicon Zoo о некоторых отсутствующих заголовках.

Worker Status
The process was created
Windows error
The operation completed successfully. (ERROR CODE: 0)
Internal module error
message: HTTP-headers - are expected  
type: ZooException 
file: Jobs\JobFastCgi.cpp 
line: 391 
version: 3.1.98.508 
STDERR
Empty stderr

Сначала я подумал, что это может быть связано с папкой temp, поэтому я установил

FILE_UPLOAD_TEMP_DIR = [os.path.join(BASE_DIR, 'temp')]

в моем файле настроек, но, похоже, ничего полезного.

Затем я обнаружил, как включить ведение журнала для django, что действительно открыло мне глаза. Теперь я знаю, откуда исходит ошибка... но я понятия не имею, что я должен сделать, чтобы обойти это..

[29/Apr/2014 11:37:00] ERROR [django.request:226] Internal Server Error: /upload/
Traceback (most recent call last):
  File "E:\mysite\venv\lib\site-packages\django\core\handlers\base.py", line 107, in get_response
    response = middleware_method(request, callback, callback_args, callback_kwargs)
  File "E:\mysite\venv\lib\site-packages\django\middleware\csrf.py", line 170, in process_view
    request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
  File "E:\mysite\venv\lib\site-packages\django\core\handlers\wsgi.py", line 146, in _get_post
    self._load_post_and_files()
  File "E:\mysite\venv\lib\site-packages\django\http\request.py", line 215, in _load_post_and_files
    self._post, self._files = self.parse_file_upload(self.META, data)
  File "E:\mysite\venv\lib\site-packages\django\http\request.py", line 180, in parse_file_upload
    return parser.parse()
  File "E:\mysite\venv\lib\site-packages\django\http\multipartparser.py", line 197, in parse
    charset)
  File "E:\mysite\venv\lib\site-packages\django\core\files\uploadhandler.py", line 135, in new_file
    self.file = TemporaryUploadedFile(self.file_name, self.content_type, 0, self.charset)
  File "E:\mysite\venv\lib\site-packages\django\core\files\uploadedfile.py", line 61, in __init__
    dir=settings.FILE_UPLOAD_TEMP_DIR)
  File "E:\mysite\venv\lib\site-packages\django\core\files\temp.py", line 27, in __init__
    dir=dir)
  File "C:\python27\lib\tempfile.py", line 300, in mkstemp
    return _mkstemp_inner(dir, prefix, suffix, flags)
  File "C:\python27\lib\tempfile.py", line 235, in _mkstemp_inner
    fd = _os.open(file, flags, 0600)
TypeError: coercing to Unicode: need string or buffer, list found

Что это значит? Мои куски как-то входят в список объектов, и я не понимаю этого?

Вот мой код для приложения, он включен в мое приложение "Блог", которое я сделал, поскольку оно является моим основным приложением, и мне показалось, что это проще, чем создавать все его собственные. Это была ошибка?

forms.py

from django import forms

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()

views.py

from django.shortcuts import render, render_to_response
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.template import RequestContext, loader
from blog.forms import UploadFileForm
from blog.models import Blog
from blog.uploads import handle_uploaded_file


def index(request):
    latest_blog_list = Blog.objects.order_by('-pub_date')[:5]
    template = loader.get_template('blog/index.html')
    context = RequestContext(request, {
        'latest_blog_list': latest_blog_list,
        })
    return HttpResponse(template.render(context))

def detail(request, blog_id):
    try:
        blog = Blog.objects.get(pk=blog_id)
    except:
        raise Http404
    return render(request, 'blog/detail.html', {'blog': blog})

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            #form.save()
            return HttpResponseRedirect('/upload/')
    else:
        form = UploadFileForm()
    return render_to_response('upload/upload.html', {'form': form}, context_instance=RequestContext(request))

uploads.py

import os

saveDir = 'E:\\uploads\\'

def handle_uploaded_file(f):
    #logging.debug('upload_here')
    if f:
        destination = open(saveDir + f.name, 'wb+')
        for chunk in f.chunks():
            destination.write(chunk)
        destination.close()

приложение urls.py

from django.conf.urls import patterns, url
from blog import views

urlpatterns = patterns('',
                       url(r'^$', views.index, name='index'),
                       url(r'^(?P<blog_id>\d+)/$', views.detail, name='detail'),
                       url(r'^upload/$', views.upload_file, name='upload'),
)

проект urls.py

from django.conf.urls import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'project.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),
    url(r'^/?', include('blog.urls', namespace="blog")),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^upload/', include('blog.urls', namespace="upload")),
)

Я должен также отметить, что части этих больших файлов фактически появляются в моем месте загрузки, но размером не более 1 мегабайта. Как будто процесс останавливается до того, как он по какой-то причине закончен Затем мне нужно остановить и перезапустить IIS, чтобы сайт снова заработал.

1 ответ

Решение

Так что здесь было несколько разных проблем. Во-первых, я обнаружил, что

TypeError: coercing to Unicode: need string or buffer, list found

ошибка не из-за объекта, отправляемого моим кодом, а из-за настройки

FILE_UPLOAD_TEMP_DIR = [os.path.join(BASE_DIR, 'temp')]

нужно вместо того, чтобы быть

FILE_UPLOAD_TEMP_DIR = os.path.join(BASE_DIR, 'temp')

Это то, что отправлялось в виде списка, когда этого не должно было быть, простая ошибка при попытке реплицировать другие поля в файле настроек проекта django. Я должен был заметить разницу между DIRS и DIR, разумеется, обозначая единственную ссылку.


Во-вторых, ошибка не исчезла после устранения проблемы. После нескольких дней, когда я бился головой, пытаясь найти, возможно, настройку IIS, которая могла бы обрезать мои загрузки до 1 МБ, или потенциально настройку django, которую я пропускал, и даже тестировать готовое приложение, только чтобы по-прежнему попасть в ту же кирпичную стену, наконец, меня осенило, когда я прочитал список переменных конфигурации в отчете об ошибках в Helicon Zoo, что я кое-что заметил...

postBuffer = 1024

Сын... Так что после небольшого исследования я обнаружил, что могу изменить этот параметр, используя переменную окружения внутри моего Helicon Zoo web.config.

POST_BUFFER = "4096"

Альт.. Я могу внезапно загрузить что-нибудь размером более 1 МБ... что-нибудь более 4 МБ обрезается, и я получаю ошибку!

Таким образом, я наконец нашел проблему, но для меня совершенно удивительно, что я не могу найти какую-либо документацию, касающуюся этой проблемы. Конечно, я не единственный, кто сталкивался с этим, поскольку это настройка по умолчанию! Хотел бы я, чтобы я мог убрать его вообще как ограничение, поскольку django сам прекрасно справляется с этим, мне действительно не нужно, чтобы Helicon делал это для меня. К сожалению, похоже, что если я установлю значение 0, то загрузка не будет работать вообще. Так что сейчас я собираюсь установить это значение на что-то произвольно высокое только потому, что, честно говоря, оно не нужно и никак не помогает мне.

ОБНОВЛЕНИЕ: Благодаря комментариям Рукебы, приведенным выше, его решение стало окончательным ответом на этот вопрос, поскольку в Twisted engine такой проблемы нет.

Другие вопросы по тегам