2022.08.12  

【Go】APIでCSVファイルと文字列を送信する

Go    

GoのAPIでクライアントからCSVファイルと文字列(id)を受け取り、読み込んだファイルの内容とidをクライアントに返すプログラムを作成したのでメモ書きします。

処理概要

まずcsvファイル(test.csv)を用意して下記のように記載します。

aaa,bbb

それから次章で紹介するコードを実行した後、下記curlコマンドを実行します。
csvfileのパスはtest.csvファイルの配置先に合わせて書き換えます。

curl -X POST -F 'id=10' -F csvfile=@/var/tmp/test.csv http://localhost:8081/data

※ -F オプションを利用すると、HTTPリクエストの Content-Type が multipart/form-data になります。

すると次のようなJSONが返ってきます。

{
    "id": "10",
    "csvfilename": "test.csv",
    "csvfilerow1": "aaa",
    "csvfilerow2": "bbb",
    "message": "処理は正常終了しました",
    "returnCode": "200"
}%    

コード内容

下記がコードの内容です。
処理内容については、簡単にですがコメントで記載しています。

package main

import (
    "encoding/csv"
    "encoding/json"
    "log"
    "net/http"
    "strconv"
)

type (
    SampleHandler struct {
        text string
    }
    SampleResponse struct {
        ID          string `json:"id"`
        CsvfileName string `json:"csvfilename"`
        CsvfileRow1 string `json:"csvfilerow1"`
        CsvfileRow2 string `json:"csvfilerow2"`
        Message     string `json:"message"`
        StatusCode  string `json:"returnCode"`
    }
    ErrorResponse struct {
        Message    string `json:"message"`
        StatusCode string `json:"returnCode"`
    }
)

func main() {
    // httpHandlerの準備
    mux := &http.ServeMux{}

    // httpHandlerの設定。第1引数に設定したURLへ接続すると第2引数のHandler処理が実行されるようになる
    mux.Handle("/data", NewSampleHandler())

    // httpサーバー起動処理。引数にはポート番号とhttpHandlerを設定する
    if err := http.ListenAndServe(":8081", mux); err != nil {
        log.Fatal(err)
    }
}

// SampleHandlerの構造体にinterfaceのhttp.Handlerを設定して返す関数
// interfaceのhttp.HandlerにはServeHTTP関数が含まれており、後の処理ListenAndServe関数から呼び出される
func NewSampleHandler() http.Handler {
    return &SampleHandler{"処理は正常終了しました"}
}

// http.Handlerのinterfaceで定義されているServeHTTP関数を作成する。
// ServeHTTP関数はListenAndServe関数内で呼び出される
func (h *SampleHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

    // http.RequestからCSVファイルを取得
    fileContent, header, err := r.FormFile("csvfile")
    if err != nil {
        ErrorResponseSend(w, "CSVAcceptError")
        return
    }
    // header.Filenameでcsvファイル名を取得できる
    csvfileName := header.Filename

    // CSVファイルの一行目を読み込む。fileContentはmultipart.File型
    reader := csv.NewReader(fileContent)
    line, err := reader.Read()
    if err != nil {
        ErrorResponseSend(w, "CSVReadError")
        return
    }

    // ステータスコード(成功)を設定
    statusCode := 200

    // httpResponseの内容を設定
    res := &SampleResponse{
        ID:          r.Form.Get("id"), // http.Requestからid情報を取得
        CsvfileName: csvfileName,
        CsvfileRow1: line[0], // csvファイルの1列名
        CsvfileRow2: line[1], // csvファイルの2列名
        Message:     h.text,
        StatusCode:  strconv.Itoa(statusCode),
    }
    // レスポンスヘッダーの設定
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")

    // ステータスコードを設定
    w.WriteHeader(statusCode)

    // httpResponseの内容を書き込む
    buf, _ := json.MarshalIndent(res, "", "    ")
    _, _ = w.Write(buf)
}

// 処理エラーのときにResponseを返す関数
func ErrorResponseSend(w http.ResponseWriter, err string) {
    // ステータスコード(失敗)を設定
    statusCode := 500

    // httpResponseの内容を設定
    res := &ErrorResponse{
        Message:    err,
        StatusCode: strconv.Itoa(statusCode),
    }
    // レスポンスヘッダーの設定
    w.Header().Set("Content-Type", "application/json; charset=UTF-8")

    // ステータスコードを設定
    w.WriteHeader(statusCode)

    // httpResponseの内容を書き込む
    buf, _ := json.MarshalIndent(res, "", "    ")
    _, _ = w.Write(buf)
}
コメント
現在コメントはありません。
コメントする
コメント入力

名前 (※ 必須)

メールアドレス (※ 必須 画面には表示されません)

送信