php vue elementUI 实现zip,excel,图片等导出功能

php vue elementUI 实现zip,excel,图片等导出功能

1.HTML:导出模板和数据按钮

 <el-button type="success" v-if="canImport" @click="export(true)" :disabled="disableExportTemplateBtn">导出模板</el-button>
 <el-button type="success" v-if="canExport" @click="export(false)" :disabled="disableExportDataBtn">导出数据</el-button>
  • v-if根据导入导出权限是否显示按钮
  • @click导出事件
  • :disabled根据导出状态判断按钮是否可点
    2.VUE:导出事件
exportTransformer(isTemplate){
    
    
				//判断是否为导出模板,按钮不可点
                if(isTemplate){
    
    
                    this.disableExportTemplateBtn = true;
                }
                else{
    
    
                    this.disableExportDataBtn = true;
                }
                //传入后台的参数(自行修改相应参数)
                let params = {
    
    'Id':this.$route.params.Id,'isTemplate':isTemplate?isTemplate:''};
                //路由地址(自行修改地址)
                let url= '/api/exportMultiple';
                this.APIRequest(
                    url,
                    'get',
                    params,
                    //返回数据类型(数据来源后边介绍)
                    'blob'
                ).then(res => {
    
    
                    if(res){
    
    
                    	//创建一个a链接
                        const link = document.createElement('a');
                        //根据Blob 对象生成一个url
                        link.href = window.URL.createObjectURL(res.blob);
                        //导出的文件名
                        if(res.fileName){
    
    
                            link.download = res.fileName;
                        }
                        //a标签点击
                        link.click();
                        this.$notify.success('导出成功');
                    }else{
    
    
                        this.$notify.error('导出失败');
                    }
                    //判断是否为导出模板,按钮可点
                    if(isTemplate){
    
    
                        this.disableExportTemplateBtn = false;
                    }
                    else{
    
    
                        this.disableExportDataBtn = false;
                    }
                });
            },

3.blob返回数据类型

export const APIRequest = function(url, method, params,responseType){
    
    
 let tempData = {
    
    
        url: url,
        method: method,
        params: params,
    };
     if(responseType != undefined){
    
    
        tempData.responseType = responseType;
    }
    return request(tempData);
};

在axios的request.js中

service.interceptors.response.use(
    response => {
    
    
        if (response.status === 200) {
    
    
        //判断如果数据类型为blob,获取文件名和返回的相应数据
            if(response.request.responseType == 'blob'){
    
    
                let disposition = response.headers['content-disposition'];
                let fileName = decodeURI(disposition.substring(disposition.indexOf('filename="')+10, disposition.length-1));
                return {
    
    fileName: fileName, blob:response.data};
            }
            return response.data;
        } else {
    
    
            Promise.reject();
        }
    },
);

4.PHP:control层和model层

//control
public function exportMultiple(Request $request){
    
    
	$id=$request->input('Id', false);
	$isTemplate=$request->input('isTemplate', true);
	$data=getData($id);
	$exportName='自定义名称'.date('YmdHis', time());
	$export=new ExportMultipleData();
    $export->exportMultiple($data,$isTemplate,$exportName);
}
//model 批量导出数据(简化版,根据导出格式自行调整数据格式)
    public function exportMultiple($data=[],$isTemplate=true, $exportName='测试文件'){
    
    
        $excelDatas = [];//填写数据的单元格
        $excelCellDatas = [];//显示的单元格
        $images = [];//图片文件
        $borders = [];//边框范围
        foreach ($data['experimentData'] as $experimentKey=>$experiment){
    
    
            $sheetName = '下边每个sheet标题的名称';
            $excelCellDatas[$sheetName] = [];
            $excelDatas[$sheetName] = [];
            $borders[$sheetName] = [];
            //从第三行开始
            $nowRow = 3;
            //MultipleField最多的列数
            $colMax=0;
            //从B列开始
            $nowCol=1;
            foreach ($experiment['experimentConfig']['fields'] as $fieldKey => $field){
    
    
                $nowRow++;
                $titleContent=$field['name'];
                $excelCellDatas[$sheetName][colNum2colLetter($nowCol)][$nowRow]=getExcelTitleStyle($titleContent);
                $nowCol++;
              if($field['type']=='Upload'){
    
    
                    $uploadPath='';
                   if(!empty($experiment['experimentFiles'][$fieldKey][0])){
    
    
                       $uploadPath=$url;//图片的地址
                   }
                    $dataContent=$sheetName.'|'.$uploadPath;
                    if(!$isTemplate){
    
    
                        $images[$sheetName][$field['name']]=$uploadPath;
                    }
                }else{
    
    
                    $dataContent=$experiment['experimentData'][$fieldKey];
                }
                $dataContent=$isTemplate? '':$dataContent;
                $excelCellDatas[$sheetName][colNum2colLetter($nowCol)][$nowRow]=getExcelContentStyle($dataContent);
                $excelDatas[$sheetName]['data_'.$nowRow.'_'.$nowCol]=colNum2colLetter($nowCol).$nowRow;
                $borders[$sheetName][]=colNum2colLetter($nowCol-1).$nowRow.':'.colNum2colLetter($nowCol).$nowRow;
                $nowCol++;
            }
            $excelCellDatas[$sheetName]['B']['2']=getExcelMainTitleStyle($sheetName,colNum2colLetter($colMax) . '2');
            $allData = [
                'excelCellDatas' => $excelCellDatas,
                'excelDatas' => $excelDatas,
                'images' => $images,
                'borders' => $borders
            ];
        }
        if(empty($images)){
    
    
            createExcelFile($allData, $exportName);
        }else{
    
    
            getZipFile($allData,$exportName);
        }
    }
    //将数字转换成excel的列号(如:A,B,AA等)
        function colNum2colLetter($num){
    
    
        $cols = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
        if($num > 25){
    
    
            $num1 = (int)($num / 25);
            $num2 = (int)($num % 25);
            return $cols[$num1].$cols[$num2];
        }
        return $cols[$num];
    }
    //获取excel表中内容相应的样式和内容(getExcelTitleStyle和getExcelMainTitleStyle根据实际情况自行调整样式)
     function getExcelContentStyle($name){
    
    
        return [
            'content' => $name,
            'style' => [
                'fontSize' => '10',
                'width' =>'20',
                'valignment' => 'center',
                'alignment' => 'center',
            ]
        ];
    }
   //没有图片,只有excel表的$allData(例子,有图片的只需在$images添加相应的图片地址即可)
   Array
(
    [excelCellDatas] => Array
        (
            [测试数据] => Array
                (
                    [B] => Array
                        (
                            [3] => Array
                                (
                                    [content] => 绕组1
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [autoSize] => 1
                                        )

                                )

                            [4] => Array
                                (
                                    [content] => 1
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [valignment] => center
                                            [alignment] => center
                                        )

                                )

                            [2] => Array
                                (
                                    [content] => 测试数据
                                    [style] => Array
                                        (
                                            [fontSize] => 20
                                            [height] => 80
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [mergeEnd] => I2
                                        )

                                )

                        )

                    [C] => Array
                        (
                            [3] => Array
                                (
                                    [content] => 分接1
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [autoSize] => 1
                                        )

                                )

                            [4] => Array
                                (
                                    [content] => 2
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [valignment] => center
                                            [alignment] => center
                                        )

                                )

                        )

                    [D] => Array
                        (
                            [3] => Array
                                (
                                    [content] => 电压 (V)
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [autoSize] => 1
                                        )

                                )

                            [4] => Array
                                (
                                    [content] => 3
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [valignment] => center
                                            [alignment] => center
                                        )

                                )

                        )

                    [E] => Array
                        (
                            [3] => Array
                                (
                                    [content] => 绕组2
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [autoSize] => 1
                                        )

                                )

                            [4] => Array
                                (
                                    [content] => 4
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [valignment] => center
                                            [alignment] => center
                                        )

                                )

                        )

                    [F] => Array
                        (
                            [3] => Array
                                (
                                    [content] => 分接2
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [autoSize] => 1
                                        )

                                )

                            [4] => Array
                                (
                                    [content] => 5
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [valignment] => center
                                            [alignment] => center
                                        )

                                )

                        )

                    [G] => Array
                        (
                            [3] => Array
                                (
                                    [content] => 电压 (V)
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [autoSize] => 1
                                        )

                                )

                            [4] => Array
                                (
                                    [content] => 6
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [valignment] => center
                                            [alignment] => center
                                        )

                                )

                        )

                    [H] => Array
                        (
                            [3] => Array
                                (
                                    [content] => 计算比值
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [autoSize] => 1
                                        )

                                )

                            [4] => Array
                                (
                                    [content] => 7
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [valignment] => center
                                            [alignment] => center
                                        )

                                )

                        )

                    [I] => Array
                        (
                            [3] => Array
                                (
                                    [content] => 实测偏差 (%)
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [bold] => 1
                                            [valignment] => center
                                            [alignment] => center
                                            [autoSize] => 1
                                        )

                                )

                            [4] => Array
                                (
                                    [content] => 8
                                    [style] => Array
                                        (
                                            [fontSize] => 10
                                            [width] => 20
                                            [valignment] => center
                                            [alignment] => center
                                        )

                                )

                        )

                )

        )

    [excelDatas] => Array
        (
            [测试数据] => Array
                (
                    [data_4_1] => B4
                    [data_4_2] => C4
                    [data_4_3] => D4
                    [data_4_4] => E4
                    [data_4_5] => F4
                    [data_4_6] => G4
                    [data_4_7] => H4
                    [data_4_8] => I4
                )

        )

    [images] => Array
        (
        )

    [borders] => Array
        (
            [测试数据] => Array
                (
                    [0] => B3:I4
                )

        )

)

5.最终导出excel表和zip(由于文章太多了,Excel类和ZipArchive类自行引入)

 function createExcelFile($allData, $fileName, $store = false)
    {
    
    
        if (stripos($_SERVER['SystemRoot'], 'windows') !== false) {
    
    
            $fileName = urlencode($fileName);
        }
        $excelFile = Excel::create($fileName, function ($excel) use ($allData) {
    
    
            $excelCellDatas = $allData['excelCellDatas'];
            $borders = $allData['borders'];
            $excelDatas = $allData['excelDatas'];
            foreach ($excelCellDatas as $sheetName => $createSheet) {
    
    
                $excelSheetDatas = isset($excelDatas[$sheetName]) ? $excelDatas[$sheetName] : [];
                if (is_numeric($sheetName)) {
    
    
                    $sheetName = "$sheetName";
                }
                $excel->sheet($sheetName, function ($sheet) use ($createSheet, $borders, $excelSheetDatas, $sheetName) {
    
    //某表格数据,边框参数,设置颜色区域,表格标题
                    $rowMax=0;
                    foreach ($createSheet as $col => $rows) {
    
    
                        $colMaxContentLen = 0;
                        foreach ($rows as $row => $cellData) {
    
    
                           if($row.$col!='2B'){
    
    
                               $colMaxContentLen = max($colMaxContentLen, strlen($cellData['content']));
                           }
                            if (isset($cellData['style'])) {
    
    
                                if (isset($cellData['style']['width']) || isset($cellData['style']['height'])) {
    
    
                                    $width = isset($cellData['style']['width']) ? (int)$cellData['style']['width'] : 8.43;
                                    $height = isset($cellData['style']['height']) ? (int)$cellData['style']['height'] : 15;
                                    $sheet->setSize($col . $row, $width, $height);
                                }
                                if (isset($cellData['style']['mergeEnd'])) {
    
    
                                    $sheet->mergeCells($col . $row . ':' . $cellData['style']['mergeEnd']);
                                }
                            }
                            $sheet->cell($col . $row, function ($cell) use ($cellData, $sheet, $excelSheetDatas, $col, $row) {
    
    
                                if (isset($cellData['style']['fontSize'])) {
    
    
                                    $cell->setFontSize((int)$cellData['style']['fontSize']);
                                }
                                if (isset($cellData['style']['bold']) && $cellData['style']['bold'] != 0) {
    
    
                                    $cell->setFontWeight();
                                }
                                if (in_array($col . $row, $excelSheetDatas)) {
    
    
                                    $cell->setBackground('#99CCFF');
                                }
                                $isImage = false;
                                $cellContentArray = explode('|', $cellData['content']);
                                if ($cellContentArray[0] != $cellData['content']) {
    
    
                                    if (isset($cellContentArray[1]) && strstr($cellContentArray[1], '/uploads/') !== false) {
    
    
                                        $imgName=explode('/',$cellContentArray[1]);
                                        $imgName=end($imgName);
                                        $cell->setValue($cellContentArray[0].DIRECTORY_SEPARATOR.$imgName);
                                        $isImage = true;
                                    }
                                }
                                if ($isImage === false) {
    
    
                                    $sheet->getCell($cell->cells)->setValueExplicit($cellData['content'], PHPExcel_Cell_DataType::TYPE_STRING);
                                }
                                if (isset($cellData['style'])) {
    
    
                                    if (isset($cellData['style']['alignment'])) {
    
    
                                        $cell->setAlignment($cellData['style']['alignment']);
                                    }
                                    if (isset($cellData['style']['valignment'])) {
    
    
                                        $cell->setValignment($cellData['style']['valignment']);
                                    }
                                }
                            });
                            $rowMax=max((int)$row,$rowMax);
                        }
                        foreach($rows as  $row => $cellData){
    
    
                            $autoSize = isset($cellData['style']['autoSize']) && $cellData['style']['autoSize'];
                            if($autoSize) {
    
    
                                $sheet->setSize($col . $row, $colMaxContentLen * 0.8, $height);
                            }
                        }
                    }
                    $sheet->mergeCells('B'.($rowMax+1) .':B'.($rowMax+1));
                    foreach ($borders[$sheetName] as $border) {
    
    
                        $leftBorder = false;
                        $rightBorder = false;
                        $borderArray = explode(':', $border);
                        $borderArray[1] = isset($borderArray[1]) ? $borderArray[1] : $borderArray[0];
                        preg_match('/([A-Z]{1,})(\d{1,})/', $borderArray[0], $left);
                        preg_match('/([A-Z]{1,})(\d{1,})/', $borderArray[1], $right);
                        if (isset($left[2]) && isset($right[2])) {
    
    
                            $leftBorder = $left[1] . $left[2] . ':' . $left[1] . $right[2];
                            $rightBorder = $right[1] . $left[2] . ':' . $right[1] . $right[2];
                        }
                        $sheet->getStyle($border)->applyFromArray([
                            'borders' => [
                                'inside' => ['style' => 'thin'],
                                'top' => ['style' => 'medium'],
                                'bottom' => ['style' => 'medium'],
                                'left' => ['style' => $leftBorder ? 'medium' : 'thin'],
                                'right' => ['style' => $rightBorder ? 'medium' : 'thin'],
                            ]
                        ]);
                    }
                });
            }
        });

        if ($store === false) {
    
    
            $excelFile->export('xls');
            return true;
        }
        if ($store) {
    
    
            $excelFile->store('xls', storage_path('temp'));
            return true;
        }
        return false;
    }
     function getZipFile($allData = [], $name = '测试文件')
    {
    
    
        $downloadFileName = $name .'.zip';
        $fileName = date('YmdHis');
        if (createExcelFile($allData, $fileName, true)) {
    
    
            $zipFile = new ZipArchive();
            $zipFileName = $fileName . '.zip';
            $zipFilePath = storage_path('temp') . DIRECTORY_SEPARATOR . $zipFileName;
            if (is_file($zipFilePath)) {
    
    
                @unlink($zipFilePath);
            }
            if ($zipFile->open($zipFilePath, ZipArchive::CREATE) === true) {
    
    
                $excelFileName = $fileName . '.xls';
                if (stripos($_SERVER['SystemRoot'], 'windows') !== false) {
    
    
                    $excelFileName = iconv('UTF-8', 'GB2312//IGNORE', $fileName) . '.xls';
                }
                $zipFile->addFile(storage_path('temp') . DIRECTORY_SEPARATOR . $excelFileName, $name. '.xls');
                foreach ($allData['images'] as $imagePath => $images) {
    
    
                    foreach ($images as $imageName => $image) {
    
    
                        $image = str_replace('/uploads/', '', $image);
                        if (is_file(public_path('uploads') . DIRECTORY_SEPARATOR . $image)) {
    
    
                            $exportImageName=explode('/',$image);
                            $zipFile->addFile(public_path('uploads') . DIRECTORY_SEPARATOR . $image, $imagePath . '/' . end($exportImageName));
                        }
                    }
                }
                $zipFile->close();
                ob_end_clean();
                $downloadFileName = urlencode($downloadFileName);
                header("Content-Type: application/force-download");//告诉浏览器强制下载
                header("Content-Transfer-Encoding: binary");//声明一个下载的文件
                header('Content-Type: application/zip');//设置文件内容类型为zip
                header('Content-Disposition:attachment;filename="'.$downloadFileName.'"');//声明文件名
                header('Content-Length: ' . filesize($zipFilePath));//声明文件大小
                error_reporting(0);
                readfile($zipFilePath);
                flush();
                exit;
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/baby_dewo/article/details/109023321