Add upload progress bar with SSE extraction status
ISO uploads now show a progress bar during file transfer (via XHR upload.onprogress) and real-time extraction status (via SSE events through the existing Hub). Falls back to plain form POST if JS is disabled. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,10 +15,24 @@ type ExtractResult struct {
|
||||
InitrdFilename string
|
||||
}
|
||||
|
||||
type ProgressFunc func(stage string, detail string)
|
||||
|
||||
var kernelCandidates = []string{"linux26", "vmlinuz", "bzImage"}
|
||||
var initrdCandidates = []string{"initrd.img", "initrd", "initrd.gz"}
|
||||
|
||||
func ExtractFromISO(r io.Reader, destDir string) (*ExtractResult, error) {
|
||||
return ExtractFromISOWithProgress(r, destDir, nil)
|
||||
}
|
||||
|
||||
func ExtractFromISOWithProgress(r io.Reader, destDir string, progress ProgressFunc) (*ExtractResult, error) {
|
||||
report := func(stage, detail string) {
|
||||
if progress != nil {
|
||||
progress(stage, detail)
|
||||
}
|
||||
}
|
||||
|
||||
report("receiving", "Writing ISO to disk...")
|
||||
|
||||
tmp, err := os.CreateTemp(filepath.Dir(destDir), "iso-upload-*.tmp")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create temp file: %w", err)
|
||||
@@ -32,6 +46,8 @@ func ExtractFromISO(r io.Reader, destDir string) (*ExtractResult, error) {
|
||||
}
|
||||
tmp.Close()
|
||||
|
||||
report("parsing", "Parsing ISO image...")
|
||||
|
||||
f, err := os.Open(tmpPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open temp ISO: %w", err)
|
||||
@@ -69,13 +85,20 @@ func ExtractFromISO(r io.Reader, destDir string) (*ExtractResult, error) {
|
||||
return nil, fmt.Errorf("no initrd found in ISO (looked for %s)", strings.Join(initrdCandidates, ", "))
|
||||
}
|
||||
|
||||
report("extracting", "Extracting kernel...")
|
||||
|
||||
if err := extractFile(kernelFile, filepath.Join(destDir, kernelName)); err != nil {
|
||||
return nil, fmt.Errorf("extract kernel: %w", err)
|
||||
}
|
||||
|
||||
report("extracting", "Extracting initrd...")
|
||||
|
||||
if err := extractFile(initrdFile, filepath.Join(destDir, initrdName)); err != nil {
|
||||
return nil, fmt.Errorf("extract initrd: %w", err)
|
||||
}
|
||||
|
||||
report("complete", "Extraction complete")
|
||||
|
||||
return &ExtractResult{
|
||||
KernelFilename: kernelName,
|
||||
InitrdFilename: initrdName,
|
||||
|
||||
@@ -18,10 +18,11 @@ type Service struct {
|
||||
}
|
||||
|
||||
type UploadParams struct {
|
||||
Name string
|
||||
Kind string
|
||||
Version string
|
||||
ISO io.Reader
|
||||
Name string
|
||||
Kind string
|
||||
Version string
|
||||
ISO io.Reader
|
||||
OnProgress ProgressFunc
|
||||
}
|
||||
|
||||
var slugRegex = regexp.MustCompile(`^[a-z0-9][a-z0-9.-]*$`)
|
||||
@@ -46,7 +47,7 @@ func (s *Service) Upload(ctx context.Context, p UploadParams) (*model.Image, err
|
||||
return nil, fmt.Errorf("create image dir: %w", err)
|
||||
}
|
||||
|
||||
result, err := ExtractFromISO(p.ISO, destDir)
|
||||
result, err := ExtractFromISOWithProgress(p.ISO, destDir, p.OnProgress)
|
||||
if err != nil {
|
||||
os.RemoveAll(destDir)
|
||||
return nil, fmt.Errorf("extract ISO: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user