Add file duration
This commit is contained in:
@@ -3,9 +3,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -27,6 +29,17 @@ func main() {
|
|||||||
if uploadDir == "" {
|
if uploadDir == "" {
|
||||||
uploadDir = "/uploads"
|
uploadDir = "/uploads"
|
||||||
}
|
}
|
||||||
|
var fileExpires time.Duration = 7 * 24 * time.Hour
|
||||||
|
|
||||||
|
dryRun := strings.ToLower(os.Getenv("DRYRUN_CLEAN")) != "false"
|
||||||
|
fileDuration := os.Getenv("FILE_DURATION")
|
||||||
|
if fileDuration != "" {
|
||||||
|
expires, err := time.ParseDuration(fileDuration)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("FILE_DURATION %s is invalid: %v", fileDuration, err)
|
||||||
|
}
|
||||||
|
fileExpires = expires
|
||||||
|
}
|
||||||
|
|
||||||
port := os.Getenv("PORT")
|
port := os.Getenv("PORT")
|
||||||
if port == "" {
|
if port == "" {
|
||||||
@@ -40,6 +53,13 @@ func main() {
|
|||||||
http.HandleFunc("/", handleRequest)
|
http.HandleFunc("/", handleRequest)
|
||||||
|
|
||||||
log.Printf("Starting server on port %s, upload directory: %s", port, uploadDir)
|
log.Printf("Starting server on port %s, upload directory: %s", port, uploadDir)
|
||||||
|
log.Printf("Files expires after: %v (DRYRUN_CLEAN=%v)", fileExpires, dryRun)
|
||||||
|
if fileExpires != 0 {
|
||||||
|
go cleanupProcedure(fileExpires, dryRun)
|
||||||
|
} else {
|
||||||
|
log.Print("Cleaning old files is disabled")
|
||||||
|
}
|
||||||
|
|
||||||
if err := http.ListenAndServe(":"+port, nil); err != nil {
|
if err := http.ListenAndServe(":"+port, nil); err != nil {
|
||||||
log.Fatalf("Server failed: %v", err)
|
log.Fatalf("Server failed: %v", err)
|
||||||
}
|
}
|
||||||
@@ -325,3 +345,95 @@ func serveFrontpage(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
indexHTML.Execute(w, pageData)
|
indexHTML.Execute(w, pageData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
|
||||||
|
func isDirEmpty(name string) (bool, error) {
|
||||||
|
f, err := os.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// Read exactly one entry.
|
||||||
|
_, err = f.ReadDir(1)
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
// EOF means there are no entries, so the directory is empty.
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If err is nil, an entry was found (not empty).
|
||||||
|
// If err is something else, a real error occurred.
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanupProcedure(duration time.Duration, dryRun bool) {
|
||||||
|
var oldFiles []string
|
||||||
|
var emptyDirs []string
|
||||||
|
|
||||||
|
deleteIfTooOld := func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if d.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := d.Info()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error cleaning file '%s' : %v", d.Name(), err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
age := time.Since(info.ModTime())
|
||||||
|
if age >= duration {
|
||||||
|
oldFiles = append(oldFiles, path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
findEmptyDirs := func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if !d.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
empty, err := isDirEmpty(path)
|
||||||
|
if empty {
|
||||||
|
emptyDirs = append(emptyDirs, path)
|
||||||
|
} else if err != nil {
|
||||||
|
log.Printf("Error cleaning directory '%s' : %v", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
|
||||||
|
filepath.WalkDir(uploadDir, deleteIfTooOld)
|
||||||
|
for _, file := range oldFiles {
|
||||||
|
if !dryRun {
|
||||||
|
err := os.Remove(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to remove expired file '%s' : %v", file, err)
|
||||||
|
} else {
|
||||||
|
log.Printf("Removed expired file '%s'", file)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("Dry run: Would remove expired file '%s'", file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filepath.WalkDir(uploadDir, findEmptyDirs)
|
||||||
|
for _, file := range emptyDirs {
|
||||||
|
if !dryRun {
|
||||||
|
err := os.Remove(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to remove empty folder '%s' : %v", file, err)
|
||||||
|
} else {
|
||||||
|
log.Printf("Removed empty folder '%s'", file)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("Dry run: Would remove empty folder '%s'", file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(6 * time.Hour)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user