Rumah > pembangunan bahagian belakang > Golang > Golang menggunakan berbilang bahagian untuk memuat naik fail besar ke API luaran. Bagaimana untuk mengelakkan masalah `io.Copy(io.Writer, io.Reader)`

Golang menggunakan berbilang bahagian untuk memuat naik fail besar ke API luaran. Bagaimana untuk mengelakkan masalah `io.Copy(io.Writer, io.Reader)`

PHPz
Lepaskan: 2024-02-06 09:45:04
ke hadapan
979 orang telah melayarinya

Golang 使用多部分将大文件上传到外部 API。如何避免`io.Copy(io.Writer, io.Reader)`问题

Kandungan soalan

Matlamat saya adalah untuk memuat naik fail besar ke POST https://somehost/media menggunakan pakej net/http terbina dalam golang.

Format HTTP untuk panggilan Api

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--
Salin selepas log masuk

Di golang, ini kodnya.

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))
}
Salin selepas log masuk

Bagaimana untuk mengelakkan io.Copy(io.Writer, io.Reader)masalah

Kod di atas berfungsi dengan baik, tetapi pada baris _, errFile3 = io.Copy(part3, file). Ini pada asasnya menyalin segala-galanya dalam fail ke dalam ingatan utama.

Bagaimana untuk mengelakkan situasi ini?

Adakah ada cara saya boleh menstrim fail besar ke api melalui multipart-formdata?

Program ini akan berjalan pada pelayan jauh. Boleh ranap jika membuka fail yang sangat besar.


Jawapan betul


Gunakan io.Pipe dan goroutine untuk menyalin fail ke permintaan tanpa memuatkan keseluruhan fail dalam memori.

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
Salin selepas log masuk

Atas ialah kandungan terperinci Golang menggunakan berbilang bahagian untuk memuat naik fail besar ke API luaran. Bagaimana untuk mengelakkan masalah `io.Copy(io.Writer, io.Reader)`. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan