📘

Go言語 csv,json,バイナリファイルの受け取り方

2024/09/18に公開

はじめに

このページではGo言語でCSVやJSONのファイルをHTTPリクエストで受け取り、構造体にマッピングする実装例と、バイナリファイルを受け取って保存するパターンについて記述します。

1. JSONファイルの受け取りと構造体へのマッピング

まず、HTTPリクエストで送信されたJSONファイルを受け取り、それをGoの構造体にデコードする方法を説明します。

構造体の定義

受け取るJSONデータをマッピングするために、対応するGoの構造体を定義します。以下は、ユーザー情報を表す例です。

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

実装例

次に、net/httpパッケージを使用して、JSONファイルを受け取るHTTPハンドラーを実装します。

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
)

// User構造体を定義
type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

// JSONファイルを受け取るハンドラー関数
func uploadJSONHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        return
    }

    var user User

    // リクエストボディからJSONをデコード
    err := json.NewDecoder(r.Body).Decode(&user)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    fmt.Fprintf(w, "Received User: %+v\n", user)
}

func main() {
    http.HandleFunc("/upload-json", uploadJSONHandler)
    log.Println("Server started at :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

動作説明

  1. クライアントはHTTP POSTリクエストでJSONデータをサーバーに送信します。
  2. サーバーはリクエストを受け取り、json.NewDecoderを使ってJSONデータをUser構造体にデコードします。
  3. デコードに成功すると、構造体にマッピングされたデータを出力します。

2. CSVファイルの受け取りと構造体へのマッピング

次に、HTTPリクエストで送信されたCSVファイルを受け取り、その内容をGoの構造体にマッピングする方法を説明します。

構造体の定義

CSVデータをマッピングするために、対応するGoの構造体を定義します。JSONと同様にユーザー情報を例とします。

type User struct {
    ID    int
    Name  string
    Email string
}

実装例

encoding/csvパッケージを使用して、CSVファイルを受け取るHTTPハンドラーを実装します。

package main

import (
    "encoding/csv"
    "fmt"
    "io"
    "log"
    "net/http"
    "strconv"
)

// User構造体を定義
type User struct {
    ID    int
    Name  string
    Email string
}

// CSVファイルを受け取るハンドラー関数
func uploadCSVHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        return
    }

    file, _, err := r.FormFile("file")
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    defer file.Close()

    reader := csv.NewReader(file)
    var users []User

    // ヘッダーを読み飛ばす
    if _, err := reader.Read(); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // CSVを読み込んで構造体にマッピング
    for {
        record, err := reader.Read()
        if err == io.EOF {
            break
        }
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        id, err := strconv.Atoi(record[0])
        if err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }

        user := User{
            ID:    id,
            Name:  record[1],
            Email: record[2],
        }
        users = append(users, user)
    }

    fmt.Fprintf(w, "Received Users: %+v\n", users)
}

func main() {
    http.HandleFunc("/upload-csv", uploadCSVHandler)
    log.Println("Server started at :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

動作説明

  1. クライアントはHTTP POSTリクエストでCSVファイルをサーバーに送信します。
  2. サーバーはリクエストを受け取り、encoding/csvパッケージを使用してCSVデータを読み込みます。
  3. 読み込んだデータをUser構造体に変換し、出力します。

3. バイナリファイルの受け取りと保存

バイナリファイル(例えば画像、動画、PDFなどの任意の形式のファイル)をHTTPリクエストで受け取り、サーバー上に保存する方法について説明します。

実装例

バイナリファイルを受け取るには、http.RequestFormFileメソッドを使用してファイルを取得し、ローカルディスクに保存します。

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
)

// バイナリファイルを受け取るハンドラー関数
func uploadFileHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        return
    }

    file, header, err := r.FormFile("file")
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    defer file.Close()

    // 保存先のパスを設定
    dst, err := os.Create(fmt.Sprintf("./uploads/%s", header.Filename))
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer dst.Close()

    // ファイルを保存
    if _, err := io.Copy(dst, file); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    fmt.Fprintf(w, "File uploaded successfully: %s\n", header.Filename)
}

func main() {
    // アップロードされたファイルを保存するディレクトリを作成
    os.MkdirAll("./uploads", os.ModePerm)

    http.HandleFunc("/upload-file", uploadFileHandler)
    log.Println("Server started at :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

動作説明

  1. クライアントはHTTP POSTリクエストでバイナリファイルをサーバーに送信します。
  2. サーバーはリクエストを受け取り、r.FormFile("file")を使ってアップロードされたファイルを取得します。
  3. ファイルを指定したディレクトリに保存し、アップロード完了メッセージを表示します。

まとめ

Go言語でJSONやCSVファイルをHTTPリクエストで受け取り、構造体にマッピングする方法と、バイナリファイルを受け取って保存する方法を説明しました。これらの手法を組み合わせることで、さまざまなタイプのデータを効率的に処理するAPIを構築できます。

Discussion