这是一个很长的问题,我非常感谢您抽出宝贵的时间-希望您可以浏览大部分粘贴的代码。
我一直在从事一个 Django 项目,该项目涉及用户上传图像(并在客户端裁剪/旋转图像,然后将最终图像发送到服务器)。我发现并使用的 JavaScript Image Cropper 是Croppie,带有一些基本的自定义。当时整个过程都在工作(大约 4 个月前,2017 年 11 月),但后来我把这个项目搁置了。
我最近恢复了它,并且通过一些新的包更新,我对 Django 代码做了一些小的修改,但没有触及 JavaScript/HTML 部分。令我惊讶的是,当我尝试上传图像时,控制台抛出了一个ConnectionAbortedError
并触发了一些下游错误,非常像在这个问题中遇到的。
完整的错误日志如下:
Traceback (most recent call last):
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 138, in run
self.finish_response()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 180, in finish_response
self.write(data)
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 274, in write
self.send_headers()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 332, in send_headers
self.send_preamble()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 255, in send_preamble
('Date: %s\r\n' % format_date_time(time.time())).encode('iso-8859-1')
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 453, in _write
result = self.stdout.write(data)
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\socketserver.py", line 775, in write
self._sock.sendall(b)
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
[03/Mar/2018 18:10:41] "GET /post_prod/ HTTP/1.1" 500 59
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 49806)
Traceback (most recent call last):
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 138, in run
self.finish_response()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 180, in finish_response
self.write(data)
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 274, in write
self.send_headers()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 332, in send_headers
self.send_preamble()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 255, in send_preamble
('Date: %s\r\n' % format_date_time(time.time())).encode('iso-8859-1')
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 453, in _write
result = self.stdout.write(data)
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\socketserver.py", line 775, in write
self._sock.sendall(b)
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 141, in run
self.handle_error()
File "W:\Dropbox\Dropbox\work\Project\b2m\python-getting-started\venv\lib\site-packages\django\core\servers\basehttp.py", line 88, in handle_error
super(ServerHandler, self).handle_error()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 368, in handle_error
self.finish_response()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 180, in finish_response
self.write(data)
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 274, in write
self.send_headers()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 331, in send_headers
if not self.origin_server or self.client_is_modern():
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 344, in client_is_modern
return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
TypeError: 'NoneType' object is not subscriptable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\socketserver.py", line 639, in process_request_thread
self.finish_request(request, client_address)
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\socketserver.py", line 361, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\socketserver.py", line 696, in __init__
self.handle()
File "W:\Dropbox\Dropbox\work\Project\b2m\python-getting-started\venv\lib\site-packages\django\core\servers\basehttp.py", line 155, in handle
handler.run(self.server.get_app())
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\handlers.py", line 144, in run
self.close()
File "c:\users\xurub\appdata\local\programs\python\python36-32\Lib\wsgiref\simple_server.py", line 35, in close
self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
该表单生成为 Django 模型表单,其中'ProductPic1','ProductPic2'
有两个 ImageField 并导致当前问题。
class PostProduct(ModelForm):
image64_1 = forms.CharField(widget=forms.HiddenInput(),required=False)
image64_2 = forms.CharField(widget=forms.HiddenInput(),required=False)
class Meta:
model = Product
fields = ('title', 'TotalPrice','AvailabilityTimeStart', 'AvailabilityTimeEnd','FromCountry' ,'FromCity', 'ToCountry','ToCity',
'Description1','Description2','Description3','Description4','ProductPic1','ProductPic2','ProductLink','AdditionalComments', 'image64_1','image64_2',)
# 'x1', 'y1', 'width1','height1', 'x2', 'y2', 'width2','height2',)
widgets = {
'FromCountry': autocomplete.Select2(url='country-autocomplete'),
'ToCountry': autocomplete.Select2(url='country-autocomplete'),
'FromCity': autocomplete.Select2(url='city-autocomplete', forward=['FromCountry']),
'ToCity': autocomplete.Select2(url='city-autocomplete', forward=['ToCountry']),
'AvailabilityTimeStart': DateInput(),
'AvailabilityTimeEnd':DateInput(),
#'AvailabilityTimeStart': SelectDateWidget(empty_label=("Choose Year", "Choose Month", "Choose Day"),),
}
模板在哪里:
<form method="post" enctype="multipart/form-data" id="post_form">
{% csrf_token %}
{{ form | crispy }}
<div>
<button type="submit" class="w3-button w3-dark-grey " name="post_prod">Submit!</button>
</div>
</form>
<!-- MODAL TO CROP THE IMAGE -->
<div class="modal fade" id="modalCrop">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Crop the photo</h4>
</div>
<div id="photoCanvas" class="modal-body">
<img src="" id="image" style="max-width: 100%;">
</div>
<div class="modal-footer">
<div class="btn-group pull-left" role="group">
<!-- <button type="button" class="btn btn-default js-zoom-in">
<span class="fa fa-plus"></span>
</button>
<button type="button" class="btn btn-default js-zoom-out">
<span class="fa fa-minus"></span>
</button>
-->
<button type="button" class="btn btn-default left-rotate">
<span class="fa fa-undo"></span>
</button>
<button type="button" class="btn btn-default right-rotate">
<span class="fa fa-repeat"></span>
</button>
</div>
<button type="button" class="btn btn-default" data-dismiss="modal">Nevermind</button>
<button type="button" class="btn btn-primary js-crop-and-upload">Crop and upload</button>
</div>
</div>
</div>
</div>
和 JavaScript:
<link rel="stylesheet" href="{% static 'css/bootstrap.css' %}" />
<link rel="stylesheet" href="{% static 'css/landing.css' %}" />
<link rel="stylesheet" href="{% static 'css/rotate.css' %}" />
<link rel="stylesheet" href="{% static 'css/croppie.css' %}" />
<!-- <script src="{% static 'js/cropper.min.js' %}"></script> -->
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<!-- <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> -->
<!-- <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<link href="https://cdn.rawgit.com/fengyuanchen/cropper/v2.0.1/dist/cropper.min.css" rel="stylesheet">
<script src="https://cdn.rawgit.com/fengyuanchen/cropper/v2.0.1/dist/cropper.min.js"></script> -->
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/croppie.js' %}"></script>
// croppie
var el = document.getElementById('image');
var picNum;
var piclink;
var vanilla;
$("#id_ProductPic1").change(function () {
if (this.files && this.files[0]) {
var reader = new FileReader();
vanilla = new Croppie(el, {
viewport: { width: 350, height: 350 },
boundary: { width: 500, height: 500 },
showZoomer: true,
enableOrientation: true
});
reader.onload = function (e) {
piclink = e.target.result;
$("#image").attr("src", piclink);
$("#modalCrop").modal("show");
picNum = 1;
}
reader.readAsDataURL(this.files[0]);
}
});
$("#id_ProductPic2").change(function () {
if (this.files && this.files[0]) {
var reader = new FileReader();
vanilla = new Croppie(el, {
viewport: { width: 350, height: 350 },
boundary: { width: 500, height: 500 },
showZoomer: true,
enableOrientation: true
});
reader.onload = function (e) {
piclink = e.target.result;
$("#image").attr("src",piclink);
$("#modalCrop").modal("show");
picNum = 2;
}
reader.readAsDataURL(this.files[0]);
}
});
$("#modalCrop").on("shown.bs.modal", function () {
vanilla.bind({
url: piclink,
});
}).on("hidden.bs.modal", function () {
vanilla.destroy();
});
var angle = 0;
$('.right-rotate').on('click', function() {
vanilla.rotate(90);
});
$('.left-rotate').on('click', function() {
vanilla.rotate(270);
});
// croppie
/* SCRIPT TO COLLECT THE DATA AND POST TO THE SERVER */
$(".js-crop-and-upload").click(function () {
if (picNum == 1){
vanilla.result('base64','jpeg').then(function(img) {
// do something with cropped blob
$("#id_image64_1").val(img);
})}
else if (picNum == 2){
vanilla.result('base64','jpeg').then(function(img) {
// do something with cropped blob
$("#id_image64_2").val(img);
})};
$("#modalCrop").modal("hide");
});
有关错误的更多信息: 1. 即使在抛出错误之后,只要正确填写表单的其他部分,仍然可以提交和发布 - 只是帖子没有附加图像。2. 当我完成选择要上传的文件/图像时抛出错误。单击选择文件按钮-选择图像-单击打开-错误抛出-图像打开,您可以执行裁剪和旋转-单击裁剪和上传-模态关闭并返回表单-继续提交表单-没有图像数据传递给服务器。
我很困惑,因为从 4 个月前的工作到现在没有工作,我所做的改变很少,特别是我很确定我根本没有接触过 JavaScript 部分。
Django 版本可能已经改变 - 我现在使用的是Django 1.11.7,但我不记得我之前使用的是什么。此外,虽然我对 JavaScript 不太熟悉,但似乎没有任何与连接相关的东西 - 不是所有事情都在客户端完成吗?
如果您需要更多信息来帮助查明问题,请告诉我。
提前致谢!