✔️

GoでファイルのValidation方法など

2022/02/23に公開

はじめに

平下CTO@sweeepです。Go言語でよく使うファイルのValidation方法などについて解説します。
本記事の内容です。

  • ファイルサイズチェック
  • ファイルのValidation
  • ファイル拡張子からContentTypeへの変換
  • 使い方
  • 実行結果

ファイルサイズチェック

定義済みファイルサイズより大きければファイルサイズとエラーを返します。問題なければファイルサイズとnilを返します。

utils/file.go
const (
	MaxSize = 10 * 1024 * 1024 // 10MB
)

var (
	ErrFileSize   = errors.New("file size error")
)

func CheckFileSize(size int64) (int64, error) {
	if size > MaxSize { // MaxSizeより大きい場合はエラー
		return size, fmt.Errorf("size: %v error: %w", size, ErrFileSize)
	}
	return size, nil
}

ファイルのValidation

GoのhttpパッケージのDetectContentTypeという関数を利用します。
https://pkg.go.dev/net/http#DetectContentType
以下のように*[]byteを渡してMIMEタイプ:メディアタイプを取得します。

mine := http.DetectContentType(*data)

下記はJPEG or PNGを許可する場合、取得したMIMEタイプをチェックし、該当した場合はJEPG or PNGのMINEタイプとnilを、該当しない場合は取得したMINEタイプとエラーを返します。

utils/file.go
var (
	JPEG    = "image/jpeg"
	PNG     = "image/png"
)

func ValidateFile(data *[]byte) (string, error) {
	mine := http.DetectContentType(*data)

	switch {
	case mine == JPEG: // MINEタイプimage/jpeg
		return mine, nil
	case mine == PNG: // MINEタイプがimage/png
		return mine, nil
	default:
		return mine, fmt.Errorf("mine: %v error: %w", mine, ErrValidation)
	}
}

ファイル拡張子からContentTypeへの変換

HTTPヘッダーにContent-TypeへリソースのMIMEタイプ埋めて返したい場合があると思います。
まずは以下の関数でファイル名から拡張子を取得します。

utils/file.go
func ExtractExt(name string) string {
	pos := strings.LastIndex(name, ".")

	// .から後ろをスライスで取得
	return name[pos:]
}

ファイルの拡張子から該当した場合はJPEG or PNGのMINEタイプを、該当しない場合は取得した拡張子を返します。

utils/file.go
var (
	JPG     = "image/jpeg"
	PNG     = "image/png"
	ExtJPG  = ".jpg"
	ExtJPEG = ".jpeg"
	ExtPNG  = ".png"
)

func ExtToContentType(ext string) (string, error) {
	switch {
	case ext == ExtJPG: // 拡張子が".jpg"の場合 ContentType:image/jpeg
		return JPEG, nil
	case ext == ExtJPEG: // 拡張子が".jpeg"の場合 ContentType:image/jpeg
		return JPEG, nil
	case ext == ExtPNG: // 拡張子が".png"の場合 ContentType:image/png
		return PNG, nil
	default:
		return ext, fmt.Errorf("extension: %v error: %w", ext, ErrNotFound)
	}
}

使い方

以下にサンプル示します。

  • サンプルファイルをオープンし、ファイルサイズチェック
  • ファイル拡張子からメディアタイプへ変換
  • サンプルファイル読み込みしValidationの実施
main.go
import (
	"log"
	"os"

	"github.com/hirac1220/go/go-file-validate/utils/file"
)

func main() {
	// ファイルサイズチェック
	f, _ := os.Open("./sample/image.jpg") // ファイルオープン
	defer func() {
		_ = f.Close()
	}()

	fi, _ := f.Stat()
	size, err := file.CheckFileSize(fi.Size()) // ファイルサイズチェック
	if err != nil {
		log.Println(err)
	}
	log.Printf("size: %d", size)

	// ファイル拡張子からメディアタイプへ変換
	ext := file.ExtractExt(fi.Name())    // ファイル拡張子取得
	c, err := file.ExtToContentType(ext) // ファイル拡張子からメディアタイプへ変換
	if err != nil {
		log.Println(err)
	}
	log.Printf("content type: %s", c)

	// ファイルValidation
	bytes, _ := os.ReadFile("./sample/image.jpg") // ファイル読み込み
	mine, err := file.ValidateFile(&bytes)        // ファイルバリデーション
	if err != nil {
		log.Println(err)
	}
	log.Printf("mine: %s", mine)
}

実行結果

サンプルファイルに対して実行した結果は以下となります。

$ go run main.go
2022/02/23 17:51:29 size: 2604
2022/02/23 17:51:29 content type: image/jpeg
2022/02/23 17:51:29 mine: image/jpeg

まとめ

今回はGo言語でよく使うファイルのValidation方法などについて解説しました。使用したサンプルはこちらのGitHubレポジトリにあります。
https://github.com/hirac1220/go-file-validate

GitHubで編集を提案

Discussion