feat(upload): resumable chunked upload protocol for large files — init(parts≤32MB)/status/complete endpoints with fingerprint-derived deterministic uploadId (same file resumes, no restart), sessions in BOOKS_DIR/.uploads with 24h sweep, frontend uploadBook auto-switches >16MB to 8MB parts (retry x3 in place, skip received); oversize single POST now reports honest 413 too_large instead of "multipart field 'file' required" (was MaxBytesReader abort mislabeled); UPLOAD_MAX_MB wired into both compose stacks (cap total, .env.example 2048), nginx body limit drops to 32m; testCfg limit 1MB, CJK/fullwidth-colon filename proven unaffected; e2e verified with 311MB real file (39 parts, sha1 match)
This commit is contained in:
@@ -37,6 +37,12 @@ func NewRouter(cfg *config.Config, st *store.Store, rdb *redispkg.R, sc *scanner
|
||||
libs.POST("", h.AdminOnly(), h.CreateLibrary)
|
||||
libs.POST("/:id/scan", h.AdminOnly(), h.ScanLibrary)
|
||||
libs.POST("/:id/upload", h.AdminOnly(), h.Upload)
|
||||
libs.POST("/:id/upload/init", h.AdminOnly(), h.UploadInit)
|
||||
|
||||
uploads := p.Group("/uploads", h.AdminOnly())
|
||||
uploads.GET("/:uid", h.UploadStatus)
|
||||
uploads.POST("/:uid/complete", h.UploadComplete)
|
||||
uploads.PUT("/:uid/parts/:index", h.UploadPart)
|
||||
|
||||
p.GET("/books", h.ListBooks)
|
||||
p.GET("/books/:id", h.GetBook)
|
||||
|
||||
Reference in New Issue
Block a user