package photo import ( "fmt" "html/template" "io" "net/http" "os" "path/filepath" "sort" "strings" "time" "meutel.net/meutel/go-examples/photoblog/admin" ) const ( DISPLAY_SIZE = 5 // number of photos displayed on home ) var ( PHOTOEXT = [3]string{".jpg", ".jpeg", ".png"} ) type AppData struct { Username string Photos []string errors []error messages []string } type TimedFile struct { Mod time.Time Path string } type timeMap []TimedFile func (m timeMap) Len() int { return len(m) } func (m timeMap) Less(i, j int) bool { return m[i].Mod.After(m[j].Mod) } func (m timeMap) Swap(i, j int) { m[i], m[j] = m[j], m[i] } type PhotoBlog struct { *admin.AuthCookie Templates *template.Template DataDir *os.File } func RedirectHome(res http.ResponseWriter, req *http.Request) { // FIXME duplicate admin http.Redirect(res, req, "/", http.StatusSeeOther) } func IsPhoto(path string) bool { for _, ext := range PHOTOEXT { if strings.HasSuffix(path, ext) { return true } } return false } func Latest(photos timeMap) []string { latest := make([]string, 0, DISPLAY_SIZE) sort.Sort(photos) for i, v := range photos { if i > DISPLAY_SIZE { break } latest = append(latest, v.Path) } return latest } func (app *PhotoBlog) HomePage(res http.ResponseWriter, req *http.Request) { data := AppData{ Username: app.Username(res, req), } photos := make([]TimedFile, 0) filepath.Walk(app.DataDir.Name(), func(path string, info os.FileInfo, err error) error { if !info.IsDir() && IsPhoto(path) { photos = append(photos, TimedFile{ info.ModTime(), path, }) } return nil }) data.Photos = Latest(photos) app.Templates.ExecuteTemplate(res, "home.html", data) } func (app *PhotoBlog) UploadPage(res http.ResponseWriter, req *http.Request) { if !app.IsLoggedIn(res, req) { RedirectHome(res, req) return } data := make(map[string]string) switch req.Method { case "POST": message, err := app.NewPhoto(res, req) if err != nil { data["error"] = err.Error() } data["message"] = message fallthrough case "GET": app.Templates.ExecuteTemplate(res, "upload.html", data) } } func (app *PhotoBlog) NewPhoto(res http.ResponseWriter, req *http.Request) (string, error) { file, header, err := req.FormFile("file") if err != nil { return "", err } defer file.Close() // FIXME check type tmpFile, err := os.Create(filepath.Join(app.DataDir.Name(), app.Username(res, req), header.Filename)) if err != nil { return "", err } defer tmpFile.Close() sz, err := io.Copy(tmpFile, file) if err != nil { return "", err } return fmt.Sprintf("File uploaded (%d bytes)", sz), nil }