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 такой проблемы нет.