// Download a file func (t Controller) Download(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") if len(id) != 36 { http.Error(w, "Thumbnail not found", 404) return } thumb, err := models.FindThumbnail(t.DB, id) if err != nil { http.Error(w, "Thumbnail not found", 404) return } http.ServeFile(w, r, lib.LocalPath(thumb.Hash)) }
func TestLocalPath(t *testing.T) { t.Parallel() a := assert.New(t) a.Equal("files/foo", lib.LocalPath("foo")) }
// CreateThumnail builds a JPG thumbnail and can rotate if an exif bit is set. func CreateThumbnail(deps dependencies.Dependencies, r io.ReadSeeker) (string, int, error) { raw, format, err := image.Decode(r) if format == "" { return "", 0, nil } if format == "jpeg" || format == "jpg" { deps.Debug("Received JPG") orientation, err := readOrientation(r) if err == nil { deps.Debug("Rotating JPG", "orientation", orientation) raw = rotate(raw, orientation) } } deps.Debug("Thumbnail format", "fmt", format) if err != nil { deps.Error("Failed to decode image") return "", 0, err } fs := deps.Fs tmpFilePath := lib.TempFilePath("thumbnail") tmpFile, err := fs.Create(tmpFilePath) if err != nil { deps.Error("Failed to create temp file", "path", tmpFilePath) return "", 0, err } // Make sure we close. closeTmpFile := func() { if tmpFile != nil { tmpFile.Close() tmpFile = nil } } defer closeTmpFile() h := sha1.New() var wc writeCounter mw := io.MultiWriter(tmpFile, h, wc) // Generate Thumbnail image data dst := imaging.Fill(raw, 200, 200, imaging.Center, imaging.Lanczos) // Write it err = imaging.Encode(mw, dst, imaging.JPEG) if err != nil { deps.Error("Failed to encode data") return "", 0, err } hash := fmt.Sprintf("%x", h.Sum(nil)) deps.Debug("Thumbnail hash", "hash:", hash) newPath := lib.LocalPath(hash) // Move temp thumbnail to final destination. err = os.Rename(tmpFilePath, newPath) if err != nil { deps.Error("Failed to rename file") // Todo delete file return hash, int(wc), err } // Set permissons err = fs.Chmod(newPath, 0644) if err != nil { deps.Error("Failed to set permissions", "path", newPath) // Todo delete file return hash, int(wc), err } return hash, int(wc), nil }