go-examples/photoblog/photo/photo.go

135 lines
2.6 KiB
Go
Raw Normal View History

2017-07-29 11:54:23 +00:00
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
}