feat(export): platform-native delivery — TG popup+downloadFile, VK viewer, mobile share sheet
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Failing after 1m7s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Failing after 0s
CI / deploy (pull_request) Has been skipped
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Failing after 1m7s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Failing after 0s
CI / deploy (pull_request) Has been skipped
Per the on-device review, the last hop is now the most native affordance per platform, all fed by the same signed URL: - Telegram: the native showPopup chooser returns (safe here — the whole TG chain is bridge calls, which need no user activation) and both formats go to the native downloadFile dialog on iOS and Android alike. - VK: the PNG opens in VK's native photo viewer (VKWebAppShowImages) — on screen at once, saved/shared from the viewer's own controls; the GCG keeps VKWebAppDownloadFile; either falls back to a plain anchor download (the desktop iframe). The gateway now serves /dl/* via http.ServeContent (Content-Length + Range/206) — another swing at the VK Android DownloadManager hang; if it persists, the next step is the clipboard fallback for the VK-Android GCG. - Mobile browsers: the OS share sheet with the fetched file (the proven fetch-then-share pattern) — nothing lands in Downloads first; desktop keeps the anchor download. Legacy Telegram (< 8.0, no downloadFile) keeps the app modal + GCG clipboard copy and hides the image option.
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
package connectsrv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/subtle"
|
||||
"encoding/json"
|
||||
@@ -14,7 +15,6 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -466,10 +466,11 @@ func (s *Server) exportDownloadHandler() http.Handler {
|
||||
}
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("Cache-Control", "private, max-age=0")
|
||||
// Explicit length, or the body goes out chunked and Android's system
|
||||
// DownloadManager (the VKWebAppDownloadFile executor) hangs on it.
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(data)))
|
||||
_, _ = w.Write(data)
|
||||
// ServeContent (not a bare Write): the platforms' native downloaders are picky —
|
||||
// Android's system DownloadManager (the VKWebAppDownloadFile executor) hangs on a
|
||||
// chunked body of unknown length and may probe with Range. ServeContent emits
|
||||
// Content-Length, honours Range/If-* and answers 206s from the buffered artifact.
|
||||
http.ServeContent(w, r, "", time.Time{}, bytes.NewReader(data))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user