随笔 - 493  文章 - 0  评论 - 97  阅读 - 239万

利用form.submit提交表单导出文件到客户端浏览器, 提示下载!

本来是想利用ajax提交json数据到服务端, 让服务端生成一个excel文件并提示客户端浏览器下载的. 但是搞了很久发现ajax方式是无法触发浏览器弹出文件下载的.

 

网上很多的方案都是说利用form提交, 还有就是纯客户端js去生成excel文件. 这两种方案都是可行的, 今天只演示第一种.

 

浏览器上展示了一堆数据, 有个按钮是导出按钮,点击后触发一个事件, 提交数据到服务端, 由服务端来生成excel文件流并提示浏览器下载!

 

 

按钮的点击:

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
onExportExcel = () => {
 
    ....... 这里准备好需要提交到服务端的数据
 
    const inputs = {
      data,
      header,
      columnWidth,
      filename,
    };
 
    this.exportExcel('/xx1/xx2/exportExcel', inputs);
  }
 
  exportExcel(url, data)     // 导出数据到excel文件
  {
    const form = document.createElement('form');
    form.style = "display:none;";
    form.method = "post";
    form.action = url;
 
    const input = document.createElement('input');
    input.type = 'hidden';
    input.name = 'values';
    input.value = Base64.encode(JSON.stringify(data));
 
    form.appendChild(input);
    $('body').append(form);
 
    form.submit();
    form.remove();
  }

 这里用了一个Base64.encode()接口(下载), 这里是关键, 因为普通的input表单一般是用于传递字符串的, 但是因为我这里要传递的是一个object对象(也可认为是json数据), 所以我就想到了将json序列化后并base64编码下(不编码的话, 服务端接收到的值有可能json_decode会失败).  ==> 所以服务端在接收时要采取相反的方向先base64_decode, 再调用json_decode才能得到原始的json数据!

 

服务端代码(php, thinkcmf5.0):

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
public function exportExcel()
    {
        $values = request()->post('values');
        $values = base64_decode($values);
 
        $list = json_decode($values, true);
        if(!$list)
        {
            _return(1, '没有数据, 无法导出到文件');
        }
 
        log_message($list);
 
        $data = $list['data'];
        $header = $list['header'];
        $columnWidth = $list['columnWidth'];
        $filename = $list['filename'];
 
        if (empty($data) || empty($header) || empty($filename)) {
            $this->success('success');
            return;
        }
 
        ExcelModule::exportFile($data, $header, $columnWidth, $filename);
    }

 ExcelModule::exportFile是我自已写的一个类, 封装的一个静态接口函数

 

复制代码
 1 class ExcelModule
 2 {
 3     /**
 4      * 导出数据到excel文件并提供下载
 5      * @param array $data
 6      * @param array $fileheader
 7      * @param array $columnWidth
 8      * @param $savefile
 9      * @param string $sheetname
10      * @throws \PHPExcel_Exception
11      * @throws \PHPExcel_Reader_Exception
12      * @throws \PHPExcel_Writer_Exception
13      */
14     public static function exportFile(array $data, array $fileheader, array $columnWidth, $savefile, $sheetname = 'MySheet')
15     {
16         Vendor('PHPExcel.PHPExcel.IOFactory');
17         $excel = new \PHPExcel();
18         //防止中文命名,下载时ie9及其他情况下的文件名称乱码
19 //        iconv('UTF-8', 'GB2312', $savefile);
20         $objActSheet = $excel->getActiveSheet();
21         //根据有生成的excel多少列,$letter长度要大于等于这个值
22         $letter = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V');
23         //设置当前的sheet
24         $excel->setActiveSheetIndex(0);
25         //设置sheet的name
26         $objActSheet->setTitle($sheetname);
27         //设置表头
28         for ($i = 0; $i < count($fileheader); $i++) {
29             // 单元宽度自适应,1.8.1版本phpexcel中文支持勉强可以,自适应后单独设置宽度无效
30             // $objActSheet->getColumnDimension("$letter[$i]")->setAutoSize(true);
31             $objActSheet->getColumnDimension("$letter[$i]")->setWidth($columnWidth[$i]);
32             // 设置表头值,这里的setCellValue第二个参数不能使用iconv,否则excel中显示false
33             $objActSheet->setCellValue("{$letter[$i]}1", $fileheader[$i]);
34             // 设置表头字体样式
35             $objActSheet->getStyle("{$letter[$i]}1")->getFont()->setName('微软雅黑');
36             //设置表头字体大小
37             $objActSheet->getStyle("{$letter[$i]}1")->getFont()->setSize(12);
38             //设置表头字体是否加粗
39             // $objActSheet->getStyle("{$letter[$i]}1")->getFont()->setBold(true);
40             //设置表头文字垂直居中
41             $objActSheet->getStyle("{$letter[$i]}1")->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
42             //设置文字上下居中
43             $objActSheet->getStyle("$letter[$i]")->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
44             //设置表头外的文字垂直居中
45             $excel->setActiveSheetIndex(0)->getStyle("$letter[$i]")->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
46         }
47 
48         $j = 2;
49         foreach ($data as $k => $v) {
50             $i = 0;
51             foreach ($v as $key => $value) {
52                 $objActSheet->setCellValue($letter[$i] . $j, $value);
53                 // $objActSheet->getColumnDimension("$letter[$i]")->setAutoSize(true);
54                 $objActSheet->getColumnDimension("$letter[$i]")->setWidth($columnWidth[$i]);
55                 $i++;
56             }
57             $j++;
58         }
59         header('Content-Type: application/vnd.ms-excel');
60         //下载的excel文件名称,为Excel5,后缀为xls,不过影响似乎不大
61         header('Content-Disposition: attachment;filename="' . $savefile . '.xls"');
62         header('Cache-Control: max-age=0');
63         // 用户下载excel
64         $objWriter = \PHPExcel_IOFactory::createWriter($excel, 'Excel2007');
65         $objWriter->save('php://output');
66         exit;
67     }
68 }
复制代码

我这个php服务端是thinkcmf5.0框架下的, 包含了很多现成的库!

最终效果:

 

posted on   清清飞扬  阅读(4508)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

点击右上角即可分享
微信分享提示