LoginSignup
3
0

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

Last updated at Posted at 2022-02-27

はじめに

こちらはzennの記事の転載となります。

平下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レポジトリにあります。

ここまで読んでいただきありがとうございました!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0