GoでPDFファイルを作成し、Zip化する

## はじめに
標題通り、GoでPDFファイルを作成し、Zip化する記事です。本記事では、PDFをzipに直接保存する事でディレクトリにPDFファイルを保存しない方法です。

## 実装
```shell:ディレクトリ構成
~/go/src/go_pdf_zip$ tree
.
├── go.mod
├── go.sum
├── main.go
└── sample.zip
1 directory, 4 files
```

```go:main.go
package main

import (
	"archive/zip"
	"bytes"
	"fmt"
	"io"
	"os"

	"github.com/jung-kurt/gofpdf"
)

func createPDF() (*bytes.Buffer, error) {
	var buf bytes.Buffer

	pdf := gofpdf.New("P", "mm", "A4", "")
	pdf.AddPage()
	pdf.SetFont("Arial", "B", 16)
	pdf.Cell(40, 10, "Hello, PDF!")

	err := pdf.Output(&buf)
	if err != nil {
		return nil, err
	}

	return &buf, nil
}

func addToZip(zipWriter *zip.Writer, filename string, data []byte) error {
	header := &zip.FileHeader{
		Name:   filename,
		Method: zip.Deflate,
	}

	writer, err := zipWriter.CreateHeader(header)
	if err != nil {
		return err
	}

	_, err = io.Copy(writer, bytes.NewReader(data))
	return err
}

func main() {
	// Create a zip file and add the sample PDF files
	zipFilename := "sample.zip"
	zipFile, err := os.Create(zipFilename)
	if err != nil {
		fmt.Println("Error creating zip file:", err)
		return
	}
	defer zipFile.Close()

	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()

	// Generate and add the sample PDF files to the zip archive
	for i := 1; i <= 3; i++ {
		pdfData, err := createPDF()
		if err != nil {
			fmt.Println("Error creating PDF:", err)
			return
		}

		err = addToZip(zipWriter, fmt.Sprintf("sample%d.pdf", i), pdfData.Bytes())
		if err != nil {
			fmt.Println("Error adding to zip:", err)
			return
		}
		fmt.Println("Added to zip: sample", i)
	}

	fmt.Println("Zip file created:", zipFilename)
}
```
→実行すると、`sample.zip`ファイルが作成される。


```go:改良版のmain.go
package main

import (
	"archive/zip"
	"bytes"
	"fmt"
	"io"
	"log"
	"os"

	"github.com/go-pdf/fpdf"
)

func main() {
    zipWriter, err := zipWriterGenerator("sample8.zip")
    if err != nil {
        log.Fatal(err)
        return
    }
    defer zipWriter.Close()

    pdfBuffer, err := createPDF()
    if err != nil {
        log.Fatal(err)
        return
    }

    err = addToZip(zipWriter, "sample111.pdf", pdfBuffer.Bytes())
    if err != nil {
        log.Fatal(err)
    }
    err = addToZip(zipWriter, "sample222.pdf", pdfBuffer.Bytes())
    if err != nil {
        log.Fatal(err)
    }
    err = addToZip(zipWriter, "sample3333.pdf", pdfBuffer.Bytes())
    if err != nil {
        log.Fatal(err)
    }

    log.Println("PDFs created and added to ZIP archive successfully.")
}

func createPDF() (*bytes.Buffer, error) {
	pdf := fpdf.New("P", "mm", "A4", "")

	// ページを追加
	pdf.AddPage()

	// フォントを設定
	pdf.SetFont("Arial", "B", 16)

	// テキストを追加
	pdf.Cell(40, 10, "Hello, PDF!")

	// PDFデータをバッファに取得
	pdfBuffer := bytes.Buffer{}
	err := pdf.Output(&pdfBuffer)
	if err != nil {
		log.Fatal(err)
		return nil, err
	}
	return &pdfBuffer, nil
}

func addToZip(zipWriter *zip.Writer, filename string, data []byte) error {
	header := &zip.FileHeader{
		Name:   filename,
		Method: zip.Deflate,
	}

	writer, err := zipWriter.CreateHeader(header)
	if err != nil {
		return err
	}

	_, err = io.Copy(writer, bytes.NewReader(data))
	return err
}


func zipWriterGenerator(zipFilename string) (*zip.Writer,error){
	zipFile, err := os.Create(zipFilename)
	if err != nil {
		fmt.Println("Error creating zip file:", err)
		return nil,err
	}

	zipWriter := zip.NewWriter(zipFile)
	return zipWriter,nil
}

```