前提
Goでユーザーが登録した画像を表示するプログラムを作成しようと考えております。
├─app
||ーーviews
| |ーーtemplates <-カレントフォルダ
| |ーーーtop.html
|
└─images
go.mod
1 github.com/google/uuid v1.3.0 // indirect 2 github.com/mattn/go-sqlite3 v1.14.15 // indirect 3 gopkg.in/go-ini/ini.v1 v1.67.0 // indirect
実現したいこと
- 画像を表示させる
該当のソースコード
HTML
1{{define "content"}} 2<hr> 3{{ range . }} 4<!-- 構造体TodoのContentを表示 --> 5<img src="../../../images/{{ .Picture }}" width="20%"> 6<hr> 7{{end}}
Go
1<!-- 共通レイアウトを設定 --> 2{{define "layout"}} 3<!DOCTYPE html> 4<html lang="ja"> 5 6<head> 7 <meta charset="UTF-8"> 8 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 9 <title>SampleApp</title> 10 <link rel="stylesheet" href="/static/css/bootstrap.min.css"> 11 <link rel="stylesheet" href="/static/css/form.css"> 12</head> 13 14<body> 15 {{template "navbar"}} 16 <div class="container text-center"> 17 {{template "content" . }} 18 </div> 19 20</body> 21<script src="/static/js/jquery-3.6.1.min.js"></script> 22<script src="/static/js/bootstrap.bundle.min.js"></script> 23 24</html> 25{{end}}
view.go
1// 詳細ページの表示 2func view(w http.ResponseWriter, r *http.Request, id int) { 3 4 c, err := models.GetCircle(id) 5 if err != nil { 6 log.Println(err) 7 } 8 generateHTML(w, c, "layout", "public_navbar", "circle/view") 9}
generateHTML.go
1func generateHTML(w http.ResponseWriter, data interface{}, filenames ...string) { 2 var files []string 3 for _, file := range filenames { 4 files = append(files, fmt.Sprintf("app/views/templates/%s.html", file)) 5 } 6 templates := template.Must(template.ParseFiles(files...)) 7 templates.ExecuteTemplate(w, "layout", data) 8}ateHTML.go 9
signup_circle.go
1func signup_circle(w http.ResponseWriter, r *http.Request) { 2 // GETメソッドのとき 3 if r.Method == "GET" { 4 _, err := session(w, r) 5 if err != nil { 6 generateHTML(w, nil, "layout", "public_navbar", "/Circles/signup") 7 } else { 8 http.Redirect(w, r, "/todos", 302) 9 } 10 } else if r.Method == "POST" { 11 //すべてのパラメータを取得する 12 err := r.ParseForm() 13 if err != nil { 14 log.Println(err) 15 } 16 17 // "upload" に入力された画像ファイルを取り出す 18 fileSrc, fileHeader, err := r.FormFile("upload") 19 if err != nil { 20 http.Error(w, err.Error(), http.StatusInternalServerError) 21 return 22 } 23 //ファイルをクローズしておく 24 defer fileSrc.Close() 25 26 //アップロードされたファイル名を取得 27 uploadedFileName := fileHeader.Filename 28 //アップロードされたファイルを置くパスを設定 29 imagePath := "images/" + uploadedFileName 30 31 //指定された場所に新しいファイルを作成する 32 fileDest, err := os.Create(imagePath) 33 if err != nil { 34 http.Error(w, err.Error(), http.StatusInternalServerError) 35 return 36 } 37 //ファイルをクローズしておく 38 defer fileDest.Close() 39 40 //ファイルにデータをコピーする 41 io.Copy(fileDest, fileSrc) 42 43 //構造体Userにデータを格納 44 circle := models.Circle{ 45 Name: r.PostFormValue("name"), 46 Email: r.PostFormValue("email"), 47 PassWord: r.PostFormValue("password"), 48 Picture: uploadedFileName, 49 } 50 51 // //ユーザ入力確認 52 // generateHTML(w, user, "layout", "public_navbar", "check") 53 54 //ユーザ作成 55 if err := circle.CreateCircle(); err != nil { 56 log.Println(err) 57 } 58 59 http.Redirect(w, r, "/todos", 302) 60 } 61}
startmainserver.go
1func StartMainServer() error { 2 // http.FileServerはハンドラーを返す。 3 // http.Dirは必ずFileServerの引数にする。 4 // Dirで静的ファイルを読み込む。 5 files := http.FileServer(http.Dir(config.Config.Static)) 6 http.Handle("/static/", http.StripPrefix("/static/", files))
config.go
1 Static: cfg.Section("web").Key("static").String(),
config.ini
1static = app/views
試したこと
- VScodeのGo Liveを試したときは、以下のコードで画像が表示されました。
<img src="./pokemon.jpg" width="20%">
>パス指定は合っていると思います。
現状だとファイル構成も提示されてないので「合ってないんでしょう」としか言えないのですが、
どのような配置になってるのでしょうか。ファイル構成を提示してください。
サーバーサイドのフレームワークであれば静的リソースの配置については指定や読み込む機能があるはずなので、あまり直にパスを書くべきではないとも思います。
Webルート以下に静的リソースを置かないフレームワークもありますから。
利用しているフレームワークも提示されたほうが良いです。
ファイル構成と標準net/httpで作られていることは分かりましたが、
「実行時のカレントフォルダ」がどこなのかと「Goのコード(抜粋でもよい)」を示してほしい。
あとは静的ファイルをどうやってサーブしているかの該当コードが欲しいです。
お世話になっております。
私の質問力不足でご迷惑をおかけして申し訳ございません。
どのようにしてサーブしているかの該当コードを載せました。
そのカレントフォルダtemplatesの下に「images/アップロードファイル名」でファイルを作ろうとしてしまいます。
そんなフォルダは無いのでエラーになる様な気がします。エラーにならずにアップロードはできていますか?
あと、アップロード済みのファイルを読み込んで返す部分の実装が見当たりません。
/static配下のファイル群をサーブしている実装はありますか?
お世話になっております。
実行すると、imagesフォルダの中にアップロードされます。
そこが期待通りに動くということはappやimagesの親フォルダがカレントフォルダになっているのでは?
あと/static配下をどうやってサーブしているかなども開示されなければ回答は難しいです。
nobonobo様、お世話になっております。
/static配下をどのようにサーブしているか載せました。
どうぞよろしくお願いいたします。
カレントフォルダをtemplatesフォルダ基準と誤解されていませんか?
os.Createに渡される相対パスは「カレントフォルダパス」を基準として処理されます。
Goのプロセスを起動した時のフォルダです。
プログラム内ではos.Getwd()にてカレントフォルダは取得できますので確認ください。
テンプレート(HTML)に書く内容に基準となるパスはURLをベースとします。
osパッケージによるファイル操作は「カレントフォルダ」をベースとします。
これらは基準が異なるので双方それぞれの基準を意識してコードを書くことが必要です。
コードを見る限りなにか相対パスの扱いに誤解があるように見えます。
「URLのパスツリー」と「ファイルシステムのパスツリー」は別物で誰かが紐づけてあげる必要があります。
/static/というURLを./static/というフォルダに紐づけているコードがあるので、/static/以下のURLは./static/フォルダ以下とマッチするようになりブラウザからファイルシステムが見えるということです。
imagesフォルダは./staticフォルダ配下ではなさそうに見えるのでimagesフォルダ配下を別途URL側に紐づける実装が必要です。
(この辺りはっきりしたいのならstaticフォルダをフォルダツリーに追記して欲しい)
その実装はstaticフォルダ同様「http.FileServerを使うハンドラ」か「パスを解釈してos.Openしてその内容をレスポンスとして返すハンドラ」という内容がメジャーです。
回答1件
あなたの回答
tips
プレビュー