【问题标题】:How to have a progress bar with uploading a file in Django 3.0.4如何在 Django 3.0.4 中上传文件的进度条
【发布时间】:2020-07-16 09:45:34
【问题描述】:

这可以通过 Ajax 和 Jquery 轻松完成,但是这个版本的 Django 似乎让它变得更加困难。它需要'{% csrf_token %}'(没有这个会抛出错误)并且在按下提交时自动提交文件。

<form
  id="data_upload"
  method="POST"
  enctype="multipart/form-data"
  class="form-horizontal"
>
  {% csrf_token %}
  <div class="input-group mb-3">
    <div class="custom-file">
      <input
        id="file_select"
        type="file"
        class="custom-file-input"
        id="inputGroupFile02"
        accept=".csv, .xslx"
        name="file"
      />
      <label
        id="submit_label"
        class="custom-file-label"
        for="inputGroupFile02"
        aria-describedby="inputGroupFileAddon02"
        >Upload CSV or Excel file</label
      >
    </div>
    <div class="input-group-append">
      <button
        id="upload_button"
        type="submit"
        class="input-group-text btn"
        id="inputGroupFileAddon02"
        disabled
      >
        Upload
      </button>
    </div>
  </div>
  <div class="d-flex justify-content-center">
    <div
      id="loading_div"
      class="spinner-border"
      role="status"
      style="display: none;"
    >
      <span class="sr-only">Loading...</span>
    </div>
  </div>
</form>

这里是ajax

  $(document).ready(function () {
    $("#data_upload").submit(function (event) {
      event.preventDefault();
      var fd = new FormData
      fd.append('file', file_input[0].files[0])

      $.ajax({
        xhr: function () {
          var xhr = new window.XMLHttpRequest()

          xhr.upload.addEventListener("progress", progressHandler, false);
          xhr.addEventListener("load", completeHandler, false);
          xhr.addEventListener("error", errorHandler, false);
          xhr.addEventListener("abort", abortHandler, false);

          return xhr;
        },
        url: window.location.href,
        type: "POST",
        data: fd,
        processData: false,
        contentType: false,
        success: function (result) {
          alert('WOOOO!')
        },
      });
    });
  });

urls.py

urlpatterns = [
    path('upload', UploadView.as_view(), name="upload"),
]

查看.py

class UploadView(TemplateView):
    def get(self, request, *args, **kwargs):
        return render(request, 'upload_datatable.html')

    def post(self, request, *args, **kwargs):
        uploaded_file = request.FILES['file']
        uploaded_file_name = uploaded_file.name

        if len(uploaded_file) != 0:
            if uploaded_file_name.endswith('.csv'):
                file_path = self.upload_csv_to_data(uploaded_file)
            elif uploaded_file_name.endswith('xlsx'):
                file_path = self.upload_excel(uploaded_file)
            else:
                return HttpResponse({'error': 'Not valid CSV or Excel'}, content_type="application/json",
                                    status_code=400)
        else:
            return HttpResponse({'error': 'No Data'}, content_type="application/json", status_code=400)

    def upload_csv_to_data(self, file):
        id = str(uuid.uuid4())
        with open(f'data/{id}.csv', 'wb+') as destination:
            for chunk in file.chunks():
                destination.write(chunk)

        return f'data/{id}'

    def upload_excel_to_data(self, file):
        id = str(uuid.uuid4())
        with open(f'data/{id}.txt', 'wb+') as destination:
            for chunk in file.chunks():
                destination.write(chunk)

        return f'data/{id}'

    def is_csv_file(self, file):
        try:
            dialect = csv.Sniffer().sniff(file.read(1024))
            file.seek(0)

            return True
        except csv.Error:
            return False

    def is_excel_file(self, file):
        try:
            book = open_workbook(file)

            return True
        except XLRDError as e:
            return False

因此,当我使用 preventDefault 来阻止 Django 发送任何内容时,但是当我查看网络时,没有发送任何内容并且“WOOOOO!”没有被打印,并且我在 Django 中的 POST 端点处的断点没有被触发。所以我不认为 ajax 正在发送文件,但同时我没有收到任何错误。有什么建议吗?

【问题讨论】:

  • 能否也分享一下ajax代码
  • 添加了ajax代码
  • 好吧,您正在上传文件两次。在 /upload POST 方法中实际上不这样做,而仅通过 ajax 代码这样做怎么样?然后在 /upload 方法中检查上传的状态,并在 ajax 上传完成后处理文件。
  • @rolando。那么您是否建议从 html 中删除 POST 并使用 jquery 处理它?
  • 或者直接丢弃POST方法中的上传数据,因为上传是由ajax处理的。当您正在更改应用程序的状态时,根本不使用 POST 似乎很脏。

标签: django file upload


【解决方案1】:

即使我删除时没有引发错误

    xhr: function () {
      var xhr = new window.XMLHttpRequest()

      xhr.upload.addEventListener("progress", progressHandler, false);
      xhr.addEventListener("load", completeHandler, false);
      xhr.addEventListener("error", errorHandler, false);
      xhr.addEventListener("abort", abortHandler, false);

      return xhr;
    },

它开始起作用了。

【讨论】:

    【解决方案2】:

    在实例化新的FormData 对象时传递e.currentTarget,以便在提交的信息中包含csrf_token

    ...
    var fd = new FormData(event.currentTarget)
    fd.append('file', file_input[0].files[0])
    ...
    

    【讨论】:

    • 这是个好建议。不幸的是,我尝试了它,但仍然没有任何反应。我确信这可以帮助我解决部分问题。我在 chrome 开发工具中检查了我的网络选项卡,它说没有发送任何内容,所以我不确定发生了什么。也没有错误被解决。
    • 你确认监听器一开始就被解雇了吗?
    • 我能够弄清楚,xhr 正在创建一个没有被抛出的错误。
    猜你喜欢
    • 2011-07-01
    • 2015-08-15
    • 2021-03-26
    • 2012-08-22
    • 2013-09-15
    • 2011-02-24
    • 1970-01-01
    相关资源
    最近更新 更多