Hi all, I'm looking at multipart/x-mixed-replace-based image streaming (mjpeg-style, but with PNG in my case), and would like to allow code to push a new image immediately. This look roughly like this (error handling elided for brevity):
m := multipart.NewWriter()
defer m.Close()
w.Header().Set("Content-Type", "multipart/x-mixed-replace; boundary="+m.Boundary())
h := textproto.MIMEHeader{}
h.Set("Content-Type", "image/png")
for {
buf := <-c // Channel with PNG data
h.Set("Content-Length", fmt.Sprint(len(buf)))
mw, _ := m.CreatePart(h)
mw.Write(buf)
w.(http.Flusher).Flush()
}
Writing PNGs to channel c will indeed display the image to the screen, but one image later. Specifically, it's the
m.CreatePart call that completes the last part by emitting the final --BOUNDARY\r\n. Unfortunately, I can't call it immediately after mw.Write, because I don't necessarily know the Content-Length for the next image. A workaround that does work is this:
mw, _ := m.CreatePart(h)
mw.Write(buf)
mw, _ = m.CreatePart(h) // Yes, again
mw.Write(buf)
w.(http.Flusher).Flush()
Notably, calling m.Close() wouldn't be appropriate here. While CreatePart write \r\n--BOUNDARY\r\n, Close would write \r\n--BOUNDARY--\r\n. Apparently that extra -- is enough to make the browser disregard everything that follows.
While this can be worked around by not using the mime/multipart library, I think it's a reasonable API change (but an API change nonetheless) to add a FlushLastPart method to Writer. WDYT?