• Python flask使用ajax上传文件


    前言

    JS

    为什么要用ajax来提交
    在使用from提交时,浏览器会向服务器发送选中的文件的内容而不仅仅是发送文件名。

    为安全起见,即file-upload 元素不允许 HTML 作者或 JavaScript 程序员指定一个默认的文件名。HTML value 属性被忽略,并且对于此类元素来说,value属性是只读的,这意味着只有用户可以输入一个文件名。当用户选择或编辑一个文件名时,file-upload 元素触发 onchange 事件句柄。

    利用form提交会导致页面刷新,体验不好,所以使用AJAX进行文件上传是个不错的选择。但这需要我们自己来组织通过POST请求发送的内容
    FormData对象

    通过FormData对象可以组装一组用 XMLHttpRequest发送请求的键/值对。它可以更灵活方便的发送表单数据,因为可以独立于表单使用。如果你把表单的编码类型设置为multipart/form-data ,则通过FormData传输的数据格式和表单通过submit() 方法传输的数据格式相同。 —— MDN web docs

    Form的enctype属性

    enctype这个属性管理的是表单的MIME编码,它一共有三个属性:

    描述
    application/x-www-form-urlencoded在发送前编码所有字符(默认)
    multipart/form-data不对字符编码,用来制定传输数据的特殊类型,如mp3、jpg
    text/plain纯文本传输

    Input

    value保存了用户指定的文件的名称
    type=“file”设置input类型为file
    multiple=“multiple”可多选,不设置为单选
    accept=“…”设置可选文件的MIME_type。在设置之后点击选择文件按钮会默认显示符合设置的MIME_type的文件(存在兼容性)。具体的文件类型对应的MIME类型可以搜索到,这里列出我用到的类型:

    MIME类型(更多直接百度,类型超乎你的想想)

    文件类型MIME类型
    .txttext/plain
    .pdfapplication/pdf
    .docapplication/msword
    .docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.document
    .xlsapplication/vnd.ms-excel
    .pptapplication/vnd.ms-powerpoint
    .pptxapplication/vnd.openxmlformats-officedocument.presentationml.presentation

    上传单个文件

    html代码部分

    <form   id="uploadForm"  method="post" enctype="multipart/form-data">
      <label  >上传电子书label>
      <input type="file"  name="file" >
      <button  id="upload" type="button"  name="button" >上传button>
      br>
      br>
      br>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    javascript代码部分

    <script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/layer/3.5.1/layer.js "></script>
    <script>
      $("#upload").click(function(){
      var formData = new FormData($('#uploadForm')[0]);
      $.ajax({
        type: 'post',
        url: "{{ url_for('.regression_report') }}", //上传文件的请求路径必须是绝对路劲
        data: formData,
        cache: false,
        processData: false,
        contentType: false,
        success:function(data){
          // 这里是访问成功时被自动执行的代码
          // 拆分返回值信息(具体返回什么东西就看视图函数中定义的json格式)
          status_ret = data.status;
          errmsg_ret = data.errmsg;
          layer.msg(errmsg_ret);
          switch (status_ret){
            case 0:
              setTimeout(function(){window.location.href = "{{ url_for('.regression_report') }}";},"2000");
              break
            default:
              setTimeout(function(){window.location.href = "{{ url_for('.regression_report') }}";},"2000");
              break
          }
        },
        error:function(jqXHR){
          // 这里是访问失败时被自动调用的代码
        }
      });
    });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    当你的页面样式比较多的时候,可能上述方法无法传入文件,下面这种方法比较强,推荐看看

    <form class="info" method="post" enctype="multipart/form-data">
      <div class="form-group">
        <label>File uploadlabel>
        <input id="id_regression_html" type="file" name="regression_html" class="file-upload-default">
        <div class="input-group col-xs-12">
          <input type="text" class="form-control file-upload-info" disabled="" placeholder="Upload Regression.html">
          <span class="input-group-append">
            <button id="html_upload" class="file-upload-browse btn btn-gradient-primary" type="button">Html Uploadbutton>
          span>
        div>
      div>
      <button id="id_ajax_submit" type="button" class="btn btn-gradient-primary mr-2">Submitbutton>
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    <script src="https://cdn.bootcdn.net/ajax/libs/layer/3.5.1/layer.js "></script>
    <script>
          $("#id_ajax_submit").click(function(){
          // var formData = new FormData($('#uploadForm')[0]);
          let formData = new FormData();
          let my_file = document.getElementById('id_regression_html');
          // @Param: 
          // @Param: myFile.file[0]为第一个文件(单选),多个文件(多选)则要循环添加
          formData.append('regression_html',my_file.files[0]);
      
            $.ajax({
                type: 'post',
                url: "{{ url_for('.regression_report') }}", //上传文件的请求路径必须是绝对路劲
                data: formData,
                cache: false,
                async: false,
                processData: false, //告诉jquery不要处理发送的数据
                contentType: false, //告诉jquery不要设置content-Type请求头
                success:function(data){
                // 这里是访问成功时被自动执行的代码
                // 拆分返回值信息(具体返回什么东西就看视图函数中定义的json格式)
                status_ret = data.status;
                errmsg_ret = data.errmsg;
                layer.msg(errmsg_ret);
                switch (status_ret){
                    case 0:
                        setTimeout(function(){window.location.href = "{{ url_for('.regression_report') }}";},"2000");
                        break
                    case 1:
                        setTimeout(function(){window.location.href = "{{ url_for('.regression_report') }}";},"2000");
                        break
                    default:
                        setTimeout(function(){window.location.href = "{{ url_for('.regression_report') }}";},"2000");
                        break
                    }
                },
                error:function(jqXHR){
                  // 这里是访问失败时被自动调用的代码
                }
            });
        });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    flask 视图函数部分

    @admin_blu.route("/toolReg", methods=['GET', 'POST'])
    def regression_report():
        if request.method == "GET":
            return render_template('index.html')
        elif request.method == "POST":
            # TODO: 获取设置
            # TODO: 获取文件
            f = request.files.get('file')
            if f and f.filename.__contains__('.html'):
                upload_path = os.path.join(current_app.root_path, 'static/upload/html', f.filename)            download_path = os.path.join(current_app.root_path, 'static/upload/html', 'xlsx')
                # TODO: 类实例化,同步执行
                f.save(upload_path)
                ret = {
                    "status": 0,
                    "errmsg": "上传成功"
                }
                return jsonify(ret)
            return redirect(url_for(".index.html"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    上传多个文件

    html

    <form id="uploadForm" enctype="multipart/form-data">
      <input type="file" name="file" multiple="multiple" />
    form>
    <button id="btnUpload">上传文件button>
    
    • 1
    • 2
    • 3
    • 4

    js

    <script>
      $("#btnUpload").on("click", function(){
      var formdata = new FormData($("#uploadForm")[0]);
      alert(formdata);
      $.ajax({
        type: "post",
        url: "/Attendance/UploadFile2/",//url地址
        contentType: false,
        cache: false,
        processData: false,
        data: formdata,
        success: function (data) {
          console.log(data);
        }
      });
    });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    出问题解决方案

    //将formdata改用下面的方式试下
    var formdata = new FormData();
    var files = $("input[type='file']")[0].files;
    for (var i = 0; i < files.length; i++) {
      formdata.append("file", files[i]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    [TS 类型体操] 初体验之Pick 与 Omit
    java毕业设计鞍山丘比特房屋租赁管理系统Mybatis+系统+数据库+调试部署
    Linux内核设计与实现 第十章 内核同步
    H5 富文本快捷输入
    计算机与操作系统
    java版工程管理系统Spring Cloud+Spring Boot+Mybatis实现工程管理系统源码
    【vue】ant-design弹出框无法关闭和runtimecore提示isFucntion is not function的问题修复
    python处理xml文件
    如何正确计算导入Excel的行数(POI/NPOI)
    JS高级(二):继承、数组的一些api、Object.defineProperty()、call、apply、bind
  • 原文地址:https://blog.csdn.net/qq_33704787/article/details/126003341