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)
}