2,096

Flask–几种常用的文件导出实现方法

点击按钮导出csv,纯js生成前端的静态数据

<html>
<head>
  <p style="font-size: 20px;color: red;">使用a标签方式将json导出csv文件</p>
  <button onclick='tableToExcel()'>导出</button>
</head>
<body>
  <script>
            
    function tableToExcel(){
      //要导出的json数据
      var jsonData = [
        {
          name:'张三',
          phone:'123456789',
          email:'[email protected]'
        },
        {
          name:'李四',
          phone:'123456789',
          email:'[email protected]'
        },
        {
          name:'王五',
          phone:'123456789',
          email:'[email protected]'
        },
        {
          name:'刘六',
          phone:'123456789',
          email:'[email protected]'
        },
      ]
      //列标题,逗号隔开,每一个逗号就是隔开一个单元格
      let str = `姓名,电话,邮箱\n`;
      //增加\t为了不让表格显示科学计数法或者其他格式
      for(let i = 0 ; i < jsonData.length ; i++ ){
        for(let item in jsonData[i]){
            str+=`${jsonData[i][item] + '\t'},`;     
        }
        str+='\n';
      }
      //encodeURIComponent解决中文乱码
      let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str);
      //通过创建a标签实现
      var link = document.createElement("a");
      link.href = uri;
      //对下载的文件命名
      link.download =  "json数据表.csv";
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    }
 
</script>
</body>
</html>

点击按钮导出excel,纯js生成前端的静态数据

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
        <script src="https://cdn.bootcss.com/xlsx/0.11.5/xlsx.core.min.js"></script>
    </head>

    <body>
        <input type="file" id="excel-file">
        <script>
            $('#excel-file').change(function(e) {
                var files = e.target.files;
                var fileReader = new FileReader();
                fileReader.onload = function(ev) {
                    try {
                        var data = ev.target.result,
                            workbook = XLSX.read(data, {
                                type: 'binary'
                            }), // 以二进制流方式读取得到整份excel表格对象
                            persons = []; // 存储获取到的数据
                    } catch (e) {
                        console.log('文件类型不正确');
                        return;
                    }
    
                    // 表格的表格范围,可用于判断表头是否数量是否正确
                    var fromTo = '';
                    // 遍历每张表读取
                    for (var sheet in workbook.Sheets) {
                        if (workbook.Sheets.hasOwnProperty(sheet)) {
                            fromTo = workbook.Sheets[sheet]['!ref'];
                            // console.log(fromTo);
                            persons = persons.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
                            break; // 如果只取第一张表,就取消注释这行
                        }
                    }
                    for(var i=0;i < persons.length;i++){
                        for(var key in persons[i]){
                            persons[i][key] = persons[i][key].replace(/\s|\xA0/g,"")
                        }
                        if(persons[i]['编号']==1){
                            persons[i]['商品链接']='http://www.test.com'
                            console.log(persons[i]['商品名称'],persons[i]['商品库存'],persons[i]['商品链接'])
                        }
                    }
                    console.log(persons);
                    var jsonData = persons
                    let str = `编号,商品名称,商品链接,商品库存,出库数量,入库数量\n`;
                      //增加\t为了不让表格显示科学计数法或者其他格式
                      for(let i = 0 ; i < jsonData.length ; i++ ){
                        for(let item in jsonData[i]){
                            str+=`${jsonData[i][item]},`;     
                        }
                        str+='\n';
                      }
                      console.log(str)
                      //encodeURIComponent解决中文乱码
                      let uri = 'data:text/xls;charset=utf-8,\ufeff' + encodeURIComponent(str);
                      //通过创建a标签实现
                      var link = document.createElement("a");
                      link.href = uri;
                      //对下载的文件命名
                      link.download =  "json数据表.xls";
                      document.body.appendChild(link);
                      link.click();
                      document.body.removeChild(link);
                };   
                // 以二进制方式打开文件
                fileReader.readAsBinaryString(files[0]);

            });
        </script>

    </body>

</html>

前后端结合导出csv(python,js)

后端接口代码如下:

import csv, json
@test.route('/export_depot', methods=['POST', 'GET'])
@login_required
def export_data():
    start_ps = request.args.get('start_ps')
    end_ps = request.args.get('end_ps') if request.args.get('end_ps') else request.args.get('start_ps')
    time = datetime.now().strftime('%Y%m%d')
    path = BASE_PATH + "/app/static/media/downloadfiles/"+time+".csv"
    load_path = "/static/media/downloadfiles/"+time+".csv"
    #读取数据库数据
    datas = ...
    #encoding用于编码,防止中文乱码
    with open(path, "w", encoding='utf-8-sig') as csvfile: 
        writer = csv.writer(csvfile)
        writer.writerow(["编号","name","time"])
        for data in datas:
            writer.writerows([[data.id, data.name, data.time]])

    results = {'success':'success', 'path': load_path}

    return json.dumps(results)

前端代码如下:

  $(function(){
      $('#export_data').on('click',function(){
          $.ajax({
              url:'{{ url_for("test.export_data") }}',
              method:'GET',
              data:{'start_ps':'{{start_ps}}',
                    'end_ps':'{{end_ps}}',
                  },
              success: function(response){
                  var success = $.parseJSON(response)['success']
                  var path = $.parseJSON(response)['path']
                  if(success == 'success'){
                      //一般的文件直接访问文件地址就是下载文件(如csv, excel, 图片等)
                      window.location.href = path
                  }
              }
          })
      })
  })

上面的代码是对csv的文件的导出,一般的文件直接访问文件地址就是下载文件(如csv, excel, 图片等,其中txt格式的文件直接访问文件路径是无法下载的,而是在在前端页面把txt文件内容展示出来。接下来实现下txt的文件导出。后台接口代码如下:

#controller.py
def export_txt(load_path, last_stock):
    path = BASE_PATH + '/app'+ load_path
    with open(path, "w", encoding='utf-8-sig') as txtfile:
        txtfile.write('name   num\n')
        for k in last_stock:
            if last_stock[k]:
                txtfile.write(k)
                txtfile.write('    ')
                txtfile.write(str(last_stock[k])+'\n')
#view.py
from flask import render_template, redirect, request, url_for, send_from_directory
import json
#该接口用于保存txt文件
@test.route('/save_txt', methods=['POST', 'GET'])
@login_required
def save_txt():
    name = request.args.get('name')
    #以下同样是读取数据
    finish_dic = ...
    load_path = "/static/media/downloadfiles/"+name
    export_txt(load_path, finish_dic)

    results = {'success':'success', 'name': name}
    return json.dumps(results)

#以下接口下载txt文件, 该方法也适用于csv。excel, 图片等文件下载
@test.route('/download', methods=['POST', 'GET'])
@login_required
def download():
    filename = request.args.get("name")
    filepath=BASE_PATH + "/app/static/media/downloadfiles/"
    return send_from_directory(filepath, filename, as_attachment=True)

前端代码如下:

<script type="text/javascript">
  $(function(){
    $('#name').val('{{stock.store_id}}').hide()
    $('#form #submit').on('click', function(event){
        event.preventDefault()
        #trigger用于让某个元素模拟某个事假操作,以下是让button触发点击事件
        $('#form button').trigger('click')
        #swal是一个弹窗插件。
        swal({   
            title: "数据计算中!",   
            text: "请稍后...",  
            showConfirmButton: false 
        });
        $.ajax({
          url:'{{ url_for("inma.calcu_stock") }}',
          method:'GET',
          data:{'name':$('#form #name').val(),
                },
          success:function(response){
            var success = $.parseJSON(response)['success']
            var name = $.parseJSON(response)['name']
            if(success == 'success'){
              swal({   
                  title: '计算成功',   
                  type: "success", 
                  timer: 500,
                  showConfirmButton: false    
              });
              #下载txt改外访问下载文件接口
              window.location.href = '{{url_for("test.download")}}?name='+name
              return false;
            }
          }
        })
    })
  })
</script>

前后端结合导出excel(python,js)

后端接口代码如下:

import xlwt
#controller.py
def produce_fima_report(balance_id, type_name, start_time, end_time, filename, load_path):
    #读取数据,orders数据存储在excel表1, severs数据存储在excel表2
    orders = ...
    servers = ...

    new_workbook = xlwt.Workbook(encoding='utf-8', style_compression=0)
    write_to_excel(new_workbook, orders, "order_info")
    write_to_excel(new_workbook, servers, "server_info")
    new_workbook.save(load_path)

def write_to_excel(new_workbook, datas, sheet_name):
    new_sheet = new_workbook.add_sheet(sheet_name)
    count = 1
    if sheet_name == 'order_info':
        order_head =  ['时间','数量','名称']
        #写入标题栏
        for i in range(len(order_head)):
            new_sheet.write(0,i,order_head[i])
        #写入数据
        for data in datas:
            new_sheet.write(count,0,str(data.time))
            new_sheet.write(count,1,data.qty)
            new_sheet.write(count,2,data.name)
            count += 1 
    if sheet_name == 'server_info':
        server_head =  ['时间','金额','数量']
        #写入标题栏
        for i in range(len(server_head)):
            new_sheet.write(0,i,server_head[i]) 
        #写入数据
        for data in datas:
            new_sheet.write(count,0,str(data.time))
            new_sheet.write(count,1,data.price)
            new_sheet.write(count,2,data.num)
            count += 1
#view.py
from flask import render_template, redirect, request, url_for, send_from_directory
import json
#用于存储excel表
@test.route('/ajax/download', methods=['POST', 'GET'])
@login_required
def ajax_download():
    balance_id = request.args.get('balance_id')
    name = request.args.get('name')
    type_name = request.args.get('type_name')
    start_time = request.args.get('start_time')
    end_time = request.args.get('end_time')
    time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')

    if balance_id != 'all':
        filename = "%s-(%s)-(%s~%s)-%s.xlsx"%(name, type_name, start_time, end_time, time)
    else:
        filename = "all-(%s)-(%s~%s)-%s.xlsx"%(type_name, start_time, end_time, time)

    load_path = BASE_PATH + "/app/static/media/downloadfiles/" + filename
    produce_fima_report(balance_id, type_name, start_time, end_time, filename, load_path)
    results = {'result':'success', 'name': filename}
    return json.dumps(results)


#用于下载excel表
@test.route('/download', methods=['POST', 'GET'])
@login_required
def download():
    filename = request.args.get("name")
    filepath = BASE_PATH + "/app/static/media/downloadfiles/"
    return send_from_directory(filepath, filename, as_attachment=True)

以上就是最近有用到的几种文件导出的实现方法,个人觉得还挺实用的,实现起来也很简单。

转载请注明出处!!

发表评论

邮箱地址不会被公开。 必填项已用*标注