Skip to content

Large files fail #26

@chrisns

Description

@chrisns

Hi, seems to be large .gcode files report as success, but are not visible in the snapmaker display.
anything over around 75mb seems to be a problem, not looked at the source but maybe needs to be a multipart upload

sm2uploader-6cb9d9fbb6-zhqtw sm2uploader 2024/12/24 10:25:49 Request GET /api/version completed in 9.743µs
sm2uploader-6cb9d9fbb6-zhqtw sm2uploader 2024/12/24 10:26:16 G-Code fixed
                                         2024/12/24 10:26:30   - HTTP sending 99.5%
sm2uploader-6cb9d9fbb6-zhqtw sm2uploader 2024/12/24 10:26:30 Upload finished: lid2.gcode [127.8 MB]
sm2uploader-6cb9d9fbb6-zhqtw sm2uploader 2024/12/24 10:26:30 Request POST /api/files/local completed in 41.022942649s

luban uses superagent which appears to handle multipart attachments automatically, so maybe that's it?
https://github.com/Snapmaker/Luban/blob/a28dcecc6633bfb0f758b265a37978a2bb07c025/src/app/flux/machine/Server.js#L215

⚠️ I don't know enough go to propose a change

Copilot suggests the following:

To modify the HTTPConnector to make a multipart upload instead of a single upload, you need to adjust the Upload function. Here is an example of how you can change the Upload function to use multipart upload:

func (hc *HTTPConnector) Upload(payload *Payload) (err error) {
    finished := make(chan empty, 1)
    defer func() {
        finished <- empty{}
    }()
    go func() {
        ticker := time.NewTicker(2 * time.Second)
        for {
            select {
            case <-ticker.C:
                hc.checkStatus()
            case <-finished:
                if Debug {
                    log.Printf("-- heartbeat stopped")
                }
                ticker.Stop()
                return
            }
        }
    }()

    w := uilive.New()
    w.Start()
    log.SetOutput(w)
    defer func() {
        w.Stop()
        log.SetOutput(os.Stderr)
    }()

    // Create a multipart writer
    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    // Add the file to the multipart writer
    part, err := writer.CreateFormFile("file", payload.Name)
    if err != nil {
        return err
    }

    content, err := payload.GetContent(NoFix)
    if err != nil {
        return err
    }

    _, err = io.Copy(part, bytes.NewReader(content))
    if err != nil {
        return err
    }

    // Close the multipart writer to set the terminating boundary
    err = writer.Close()
    if err != nil {
        return err
    }

    r := hc.request(0)
    r.SetBody(body)
    r.SetHeader("Content-Type", writer.FormDataContentType())
    r.SetUploadCallbackWithInterval(func(info req.UploadInfo) {
        if info.FileSize > 0 {
            perc := float64(info.UploadedSize) / float64(info.FileSize) * 100.0
            log.Printf("  - HTTP sending %.1f%%", perc)
        } else {
            log.Printf("  - HTTP sending %s...", humanReadableSize(info.UploadedSize))
        }
    }, 35*time.Millisecond)

    _, err = r.Post(hc.URL("/upload"))
    return
}

This code creates a multipart writer, adds the file content to it, and sets the body of the request to the multipart data. Make sure to import the necessary packages:

import (
    "bytes"
    "mime/multipart"
)

This should enable the HTTPConnector to perform a multipart upload.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions