Heim >Backend-Entwicklung >Golang >Golang verwendet Multipart, um große Dateien auf eine externe API hochzuladen. So vermeiden Sie das Problem „io.Copy(io.Writer, io.Reader)'.
Mein Ziel ist es, eine große Datei mithilfe des integrierten Net/http-Pakets von Golang auf POST https://somehost/media
hochzuladen.
HTTP-Format für API-Aufruf
POST /media HTTP/1.1 Host: somehost Content-Length: 434 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="detail" More and more detail ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="file"; filename="some_big_video.mp4" Content-Type: <Content-Type header here> (data) ------WebKitFormBoundary7MA4YWxkTrZu0gW--
In Golang ist dies der Code.
package main import ( "fmt" "bytes" "mime/multipart" "os" "path/filepath" "io" "net/http" "io/ioutil" ) func main() { url := "https://somehost/media" method := "POST" payload := &bytes.Buffer{} writer := multipart.NewWriter(payload) _ = writer.WriteField("details", "more and more details") file, errFile3 := os.Open("/Users/vajahat/Downloads/some_big_video.mp4") defer file.Close() part3,errFile3 := writer.CreateFormFile("file","some_big_video.mp4") _, errFile3 = io.Copy(part3, file) if errFile3 != nil { fmt.Println(errFile3) return } err := writer.Close() if err != nil { fmt.Println(err) return } client := &http.Client {} req, err := http.NewRequest(method, url, payload) if err != nil { fmt.Println(err) return } req.Header.Set("Content-Type", writer.FormDataContentType()) res, err := client.Do(req) if err != nil { fmt.Println(err) return } defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println(err) return } fmt.Println(string(body)) }
Wie man io.Copy(io.Writer, io.Reader)
Probleme
Der obige Code funktioniert gut, aber in der _, errFile3 = io.Copy(part3, file)
-Zeile. Dadurch wird im Wesentlichen alles in der Datei in den Hauptspeicher kopiert.
Wie vermeide ich diese Situation?
Gibt es eine Möglichkeit, große Dateien über multipart-formdata
an die API zu streamen?
Das Programm wird auf einem Remote-Server ausgeführt. Kann beim Öffnen einer sehr großen Datei abstürzen.
Verwenden Sie io.Pipe und eine Goroutine, um die Datei in die Anfrage zu kopieren, ohne die gesamte Datei in den Speicher zu laden.
pr, pw := io.Pipe() writer := multipart.NewWriter(pw) ct := writer.FormDataContentType() go func() { _ = writer.WriteField("details", "more and more details") file, err := os.Open("/Users/vajahat/Downloads/some_big_video.mp4") if err != nil { pw.CloseWithError(err) return } defer file.Close() part3, err := writer.CreateFormFile("file", "some_big_video.mp4") if err != nil { pw.CloseWithError(err) return } _, err = io.Copy(part3, file) if err != nil { pw.CloseWithError(err) return } pw.CloseWithError(writer.Close()) }() client := &http.Client{} req, err := http.NewRequest(method, url, pr) if err != nil { fmt.Println(err) return } req.Header.Set("Content-Type", ct) // remaining code as before
Das obige ist der detaillierte Inhalt vonGolang verwendet Multipart, um große Dateien auf eine externe API hochzuladen. So vermeiden Sie das Problem „io.Copy(io.Writer, io.Reader)'.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!