Go语言生成excel、将excel保存到本地、将多个excel表格压缩为压缩包、在压缩文件上传OSS删除本地excel文件和压缩包

        最近在公司了个需求,主要涉及到文件导出,需要根据特定表格文件生成excel文件导出,同时对导出的excel临时保存本地,生成压缩包,将压缩包上传至OSS(Object Storage Service)后删除本地临时文件。下面的文章中将对以上涉及到的几个点编写代码实现。

Go语言对excel文件的操作

        Go中对excel文件的操作主要依赖于Excelize库,提供了一组函数,可以对XLAM / XLSM / XLSX / XLTM / XLTX文件进行读写。支持读写由Microsoft Excel™2007及以后版本生成的电子表格文档。通过高兼容性支持复杂组件,并提供流API从具有大量数据的工作表中生成或读取数据。该库需要Go 1.16或更高版本。

        首先通过以下命令获取excelize依赖:

ge get github.com/xuri/excelize/v2

        常见的对excel文件的操作包括:生成excel表格、生成sheet页、向对应sheet页中的cell单元格内填写数据(对excel文件操作的基本步骤)。代码如下:

func genExcelFile() (err error) {
    // 创建一个新的Excel文件1
	f1 := excelize.NewFile() 
	// 在Excel中创建一个新的sheet页
	f1.NewSheet("Sheet1")
	// 向工作表中写入数据
	if err = f1.SetCellValue("Sheet1", "A1", "Hello, World!"); err != nil {
		return
	}
    
    // 创建一个新的Excel文件2
	f2 := excelize.NewFile() 
	// 在Excel中创建一个新的sheet页
	f2.NewSheet("Sheet1")
	if err = f2.SetCellValue("Sheet1", "B1", 123); err != nil {
		return
	}
	return
}

        上述代码给出了对excel文件操作的基本思路实现,在公司中不可能让自己单独实现一个excel的SDK对文件进行导出操作。具体学习参考下述链接:一文搞懂Go读写Excel文件_go excel-CSDN博客

将生成的excel文件保存到本地

        我在公司中做的需求需要同时导出多个excel文件,一个excel文件又包含多个sheet页,最终测试环境导出数据量达6W条之多。我需要将导出的多个excel文件生成一个压缩包。可能会问为什么需要将excel文件暂时保存到磁盘中,而不是暂时保存到内存中等所有的excel文件生成后直接在内容中将其生成zip文件。最终数据量非常大,若将其直接保存到内存中等所有excel表格生成后,将其合并生成zip文件是非常不明智的决定,对于内存的压力巨大。正确的做法每生成一个excel文件将其保存到磁盘目录中,等到所有excel文件生成后,遍历并读取所有excel文件,每遍历一个压缩一个,最终生成一个zip文件。并在将zip文件上传至OSS后删除磁盘文件。

        在上面的步骤中我们得到了 file *excelize.File 类型的excel文件,在填充了对应sheet单元格中具体内容后,需要将其保存到磁盘。借助于和File文件绑定的SaveAs()方法可以实现。

        在得知以上方法之后,自己编写了一个简易的文件保存方法:

const(
    celFilePath = "excelFiles"
)
func saveExcelFile(file *excelize.File, sub string) (path string, err error) {
	path = filepath.Join(excelFilePath, fmt.Sprintf("%s%s", sub, "test.xlsx"))
	
	if err = file.SaveAs(path); err != nil {
		return "", err
	}
	return path, nil
}

        将对应的excel文件保存到当前项目下并且创建一个excelFiles文件夹用以保存所有excel文件。上述代码最终报错:

open excelFiles/1test.xlsx: no such file or directory

        显示对应路径不存在。之前并没有创建临时目录,我本以为SavaAs方法在对应目录不存在时会创建对应的目录,和文件,但实验过后发现并非如此。在写入本地对应目录前,需要借助os.MkdirAll()函数判断对应目录是否存在,如果不存在会创建对应的目录,包含子目录。 

        修改后代码如下所示:

func saveExcelFile(file *excelize.File, sub string) (path string, err error) {
	path = filepath.Join(excelFilePath, fmt.Sprintf("%s%s", sub, "test.xlsx"))
	if err = os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
		return "", err
	}
	if err = file.SaveAs(path); err != nil {
		return "", err
	}
	return path, nil
}

        执行创建excel,并将excel写入本地代码后在项目文件夹下创建 excelFiles 文件夹用以存储所有excel文件,效果如下:

使用压缩工具将多个excel文件压缩为压缩包

        最终根据保存的excel文件路径去遍历读取每个excel文件并将其添加到zip压缩文件中。此时需要记住 "archive/zip" 依赖中的 zip.NewWriter(zipFile) 创建zip文件写入器:

    // zip压缩文件存放路径
    zipFilePath = filepath.Join(excelFilePath, excelZipName)
	// 创建ZIP文件
	zipFile, err := os.Create(zipFilePath)
	if err != nil {
		return "", err
	}
	defer zipFile.Close()
	// 创建ZIP写入器
	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()

        随后遍历读取所有excel文件,并将其写入到zip压缩文件中。

删除临时文件及目录

        使用  os.RemoveAll(excelFilePath) 可以删除对应目录下的文件及目录。

        此外自己代码编写过程中学习了如何删除对应目录下的所有文件,不删除对应目录:

func deleteFiles(path string) error {
	// 要删除文件的目录
	// 读取目录中的所有文件
	files, err := os.ReadDir(path)
	if err != nil {
		fmt.Println(err)
		return err
	}

	// 遍历所有文件
	for _, file := range files {
		err := os.Remove(filepath.Join(path, file.Name()))
		if err != nil {
			fmt.Println(err)
			return err
		}
	}

	return nil
}

代码及效果展示 

        最终代码展示了如何创建多个excel、将excel写入本地磁盘、遍历读取磁盘excel生成zip文件、将zip文件上传到OSS(伪代码)、删除临时文件:注释defer中的删除临时目录及文件后代码如下:

package main

import (
	"archive/zip"
	"fmt"
	"github.com/xuri/excelize/v2"
	"io"
	"os"
	"path/filepath"
)

const (
	excelFilePath = "excelFiles"
	excelZipName  = "wwtTest.zip"
)

func main() {
	defer func() {
		//os.RemoveAll(excelFilePath)
	}()
	genExcelFile()
}

func genExcelFile() (err error) {
	f1 := excelize.NewFile() // 创建一个新的Excel文件
	// 在Excel中创建一个新的工作表
	f1.NewSheet("Sheet1")
	// 向工作表中写入数据
	if err = f1.SetCellValue("Sheet1", "A1", "Hello, World!"); err != nil {
		fmt.Println(err)
		return
	}
	f2 := excelize.NewFile() // 创建一个新的Excel文件

	// 在Excel中创建一个新的工作表
	f2.NewSheet("Sheet1")
	if err = f2.SetCellValue("Sheet1", "B1", 123); err != nil {
		fmt.Println(err)
		return
	}
	path1, err := saveExcelFile(f1, "1")
	if err != nil {
		fmt.Println(err)
		return
	}
	path2, err := saveExcelFile(f2, "2")
	if err != nil {
		fmt.Println(err)
		return
	}
	// 获取zip文件
	zipFilePath, _ := genZipFiles([]string{path1, path2})
	fmt.Println(zipFilePath)

    // 将zip文件上传至OSS 
    // TODO
	return
}
func saveExcelFile(file *excelize.File, sub string) (path string, err error) {
	path = filepath.Join(excelFilePath, fmt.Sprintf("%s%s", sub, "test.xlsx"))
	if err = os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
		return "", err
	}
	if err = file.SaveAs(path); err != nil {
		return "", err
	}
	return path, nil
}

func genZipFiles(filePaths []string) (zipFilePath string, err error) {
	zipFilePath = filepath.Join(excelFilePath, excelZipName)
	// 创建ZIP文件
	zipFile, err := os.Create(zipFilePath)
	if err != nil {
		return "", err
	}
	defer zipFile.Close()
	// 创建ZIP写入器
	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()
	// 遍历文件列表,逐个添加到ZIP文件中
	for _, filePath := range filePaths {
		if err = addFileToZip(zipWriter, filePath); err != nil {
			return "", err
		}
	}
	return zipFilePath, nil
}

// 将文件写入zip压缩器
func addFileToZip(zipWriter *zip.Writer, filePath string) error {
	// 打开要添加的文件
	file, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	// 获取文件信息
	fileInfo, err := file.Stat()
	if err != nil {
		return err
	}

	// 创建ZIP文件中的文件头
	zipHeader, err := zip.FileInfoHeader(fileInfo)
	if err != nil {
		return err
	}

	// 将文件头写入ZIP文件
	writer, err := zipWriter.CreateHeader(zipHeader)
	if err != nil {
		return err
	}

	// 将文件内容复制到ZIP文件中
	_, err = io.Copy(writer, file)
	if err != nil {
		return err
	}
	return nil
}

        效果如下:

参考链接

一文搞懂Go读写Excel文件_go excel-CSDN博客

 Golang 生成压缩文件教程_golang 压缩文件-CSDN博客

golang 实现多文件压缩下载_golang将多个文件压缩到一起-CSDN博客 

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值