我在Mac OS X上运行的测试服务器是最新的Django 2版本(Python3.6)。我的应用程序在Safari 11.0.2和Chrome(build 63)上都运行得很好,除了一个细节。我有这个文件上传表:
class BulkForm(AssemblyForm): # AssemblyForm itself defines a Char field.
file = forms.FileField(required=True, label='Input file')
这是由以下视图处理的(在本例中,我将其减少到最小值):
def formtest(request):
if request.method == 'POST':
form = BulkForm(request.POST, request.FILES)
if form.is_valid():
upload = request.FILES['file']
return HttpResponseRedirect(reverse('submissions'))
bulk = BulkForm()
return render(request, 'upload.html', {'bulk_form': bulk})
以及模板:
...
<div class="tab-pane fade" id="bulk">
<div class="container my-4">
<form role="form" method="post"
enctype="multipart/form-data">
{% csrf_token %}
{{ bulk_form.as_p }}
<button type="submit" name="bulk-form"
class="btn btn-primary bg-dark">
Submit
</button>
</form>
</div>
...
在Safari中,即使我尝试相同的文件,上传也会冻结:有时上传成功,有时冻结。文件大小与其卡住的可能性之间存在相关性。为了调查这个问题,我实现了自己的上载处理程序:
class SizeLimitedUploadedFile(uploadedfile.UploadedFile):
def __init__(self, name, content_type, size, charset, content_type_extra=None):
file = tempfile.NamedTemporaryFile(
buffering=settings.FILE_UPLOAD_MAX_MEMORY_SIZE, delete=False,
suffix=f'.upload.{name.split(".", 1)[1]}',
dir=settings.FILE_UPLOAD_TEMP_DIR
)
super().__init__(file, file.name, content_type, 0, charset, content_type_extra)
self.error = None
def write(self, chunk: bytes) -> int:
"""
:param chunk: bytes to write
:return: the number of bytes written
:raises FileSizeLimitReached: if file size reached
"""
newsize = self.size + len(chunk)
if newsize <= settings.FILE_UPLOAD_MAX_MEMORY_SIZE:
self.file.write(chunk)
self.size = newsize
return len(chunk)
self.error = FileSizeLimitReached
raise FileSizeLimitReached
def writelines(self, chunks: Iterable[bytes]):
"""
:param chunks: bytes to write
:raises FileSizeLimitReached: if file size reached
"""
for chunk in chunks:
self.write(chunk)
class TestFileUploadHandler(uploadhandler.FileUploadHandler):
"""
File upload handler to stream uploads into memory (used for small files).
"""
def new_file(self, *args, **kwargs):
"""
Create the file object to append to as data are coming in.
"""
print('creating new')
super().new_file(*args, **kwargs)
self.file = SizeLimitedUploadedFile(
self.file_name, self.content_type, 0,
self.charset, self.content_type_extra
)
self.counter = 0
def receive_data_chunk(self, raw_data, start):
self.counter += 1
print(f'receiving batch {self.counter}')
if self.file.error is None:
with suppress(FileSizeLimitReached):
self.file.write(raw_data)
def file_complete(self, file_size):
print('complete')
self.file.seek(0)
return self.file
然后,我替换了settings.py
中的默认上载处理程序,并多次尝试上载同一个文件。当上传按预期终止时,我总是看到1250个对TestFileUploadHandler.receive_data_chunk
的调用。当它冻结时,柜台停留在1239-1245个电话左右。我只在野生动物园见过这种行为。Chrome与内置处理程序以及我的自定义处理程序都工作得很好—它从不冻结。我试着在网上搜索这个,到目前为止,最热门的是2009年的一个thread关于一个旧的WebKit bug。我一直跟着线索走,但毫无结果。我怎样才能解决这个问题?你知道吗
更新
我已经在最新版本的Firefox和Opera上运行了测试。两者都完美无瑕。似乎这个问题与Safari无关。你知道吗
更新2
我在上传文件的过程中分析了Safari的活动。不管出于什么原因,它有时会进入一个无休止的重复页面呈现循环。你知道吗
目前没有回答
相关问题 更多 >
编程相关推荐