DRYな備忘録

Don't Repeat Yourself.

revelでfileをアップロードするもnil【revel】【Go】【html】

問題

Goのウェブフレームワークrevelでファイルをアップロードしたい。

のに、nilがアップロードされてくる。 ナンデヤ

app/views/Test/Index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>テストデータのアップロードページ</h1>
    <form name="upload" method="POST" action="/test/upload">
      <input type="file"   name="imgFile"  accept="image/png">
      <input type="submit" name="submit"   value="commit">
    </form>
  </body>
</html>

conf/routes

GET     /test        Test.Index
POST    /test/upload Test.Upload

app/controllers/app.go

import (
  "github.com/robfig/revel"
  "labix.org/v2/mgo"
  "otiai10/logServer/app/routes"
  "fmt"
  "os"
)
type Test struct {
  *revel.Controller
}
func (c Test) Index() revel.Result {
  return c.Render()
}
func (c Test) Upload(submit string, imgFile *os.File) revel.Result {
  fmt.Printf("submit  => %v\n", submit)
  fmt.Printf("imgFile => %v\n", imgFile)
  return c.Redirect(routes.Test.Index())
}

で、/testにアクセスしてファイルを選択してcommit押すと、サーバコンソールでは

submit  => commit
imgFile => <nil>

あらーん。ナンデヤ

そういえば...

むかしRailsやってて同じような問題に出会った気がする...

解決

HTMLのformタグにenctype="multipart/form-data"属性を追加 app/views/Test/Index.html抜粋

    <form name="upload" method="POST" action="/test/upload" enctype="multipart/form-data">
      <input type="file"   name="imgFile"  accept="image/png">
      <input type="submit" name="submit"   value="commit">
    </form>

revel cleanをしたあと、同じように/testにアクセスしてファイルアップロードすると、

submit  => commit
imgFile => &{0xc2000f78d0}

ビンゴであった

formのenctypeって何なの

ファイルの中身はバイナリファイルだったりテキストでもサイズが大きかったりするので、通常のURLエンコードでの送信は無理があります。この場合は、form要素のenctype属性をmultipart/form-dataに設定し、MIMEのマルチパートデータとしてファイルやその他の項目の内容を送ります。。

http://www.kanzaki.com/docs/html/htminfo32.html#enctype

なるほど、今回はちゃんと理解したでござる

f:id:otiai10:20131004173653j:plain

DRY