Manual server file uploads implemented

This commit is contained in:
Magnus Åhall 2026-06-26 08:31:54 +02:00
parent c8308664d3
commit 70b5285e16
10 changed files with 329 additions and 26 deletions

63
main.go
View file

@ -5,7 +5,6 @@ import (
"notes2/authentication"
"notes2/html_template"
appUser "notes2/user"
"os"
// Standard
"bufio"
@ -17,11 +16,13 @@ import (
"io"
"log/slog"
"net/http"
"os"
"path"
"regexp"
"strconv"
"strings"
"text/template"
"time"
)
const VERSION = "v29"
@ -71,7 +72,7 @@ func init() { // {{{
} // }}}
func initLog() { // {{{
opts := slog.HandlerOptions{}
opts.Level = slog.LevelDebug
opts.Level = slog.LevelInfo
Log = slog.New(slog.NewJSONHandler(os.Stdout, &opts))
} // }}}
func main() { // {{{
@ -141,6 +142,7 @@ func main() { // {{{
http.HandleFunc("/sync/from_server/count/{sequence}", authenticated(actionSyncFromServerCount))
http.HandleFunc("/sync/from_server/{sequence}/{offset}", authenticated(actionSyncFromServer))
http.HandleFunc("/sync/to_server", authenticated(actionSyncToServer))
http.HandleFunc("/sync/file/upload/{uuid}", authenticated(actionSyncFileUpload))
http.HandleFunc("/node/retrieve/{uuid}", authenticated(actionNodeRetrieve))
http.HandleFunc("/node/history/retrieve/{uuid}/{offset}", authenticated(actionNodeHistoryRetrieve))
@ -391,6 +393,63 @@ func actionSyncToServer(w http.ResponseWriter, r *http.Request) { // {{{
"OK": true,
})
} // }}}
func actionSyncFileUpload(w http.ResponseWriter, r *http.Request) { // {{{
uuid := r.PathValue("uuid")
session := getUserSession(r)
sentBytes, _ := strconv.Atoi(r.Header.Get("X-File-Sent-Bytes"))
totalBytes, _ := strconv.Atoi(r.Header.Get("X-File-Total-Bytes"))
// First block comes with file metadata.
file := File{}
if sentBytes == 0 {
file.UUID = uuid
file.Filename = r.Header.Get("X-File-Name")
file.Size, _ = strconv.Atoi(r.Header.Get("X-File-Size"))
file.MIME = r.Header.Get("X-File-Type")
modded, _ := strconv.ParseInt(r.Header.Get("X-File-Modified"), 10, 64)
file.Modified = time.UnixMilli(modded)
err := AddFileToDb(session.UserID, &file)
if err != nil {
Log.Error("upload", "op", "AddFileToDB", "error", err)
httpError(w, err)
return
}
fileUUIDCache[uuid] = file.ID
}
data, _ := io.ReadAll(r.Body)
var err error
switch sentBytes {
case 0:
// First block of data.
Log.Info("file_upload", "status", "new", "user", session.UserID, "uuid", uuid, "total", totalBytes)
id := fileUUIDCache[uuid]
err = FileWriteData(session.UserID, id, data, true)
case totalBytes:
// Last block of data - sent with 0 length data.
Log.Info("file_upload", "status", "done", "user", session.UserID, "uuid", uuid, "total", totalBytes)
id := fileUUIDCache[uuid]
delete(fileUUIDCache, uuid)
_, err = db.Exec(`UPDATE public.file SET upload_complete = true WHERE id = $1`, id)
default:
id := fileUUIDCache[uuid]
err = FileWriteData(session.UserID, id, data, false)
}
if err != nil {
Log.Error("upload", "error", err)
httpError(w, err)
return
}
responseData(w, map[string]any{
"OK": true,
})
} // }}}
func actionUserGetPreferences(w http.ResponseWriter, r *http.Request) { // {{{
user := getUserSession(r)