0

这是一个很长的问题,我非常感谢您抽出宝贵的时间-希望您可以浏览大部分粘贴的代码。

我一直在从事一个 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">&times;</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 不太熟悉,但似乎没有任何与连接相关的东西 - 不是所有事情都在客户端完成吗?

如果您需要更多信息来帮助查明问题,请告诉我。

提前致谢!

4

0 回答 0