2017-02-15 7 views
1

POST要求でサーバーにファイルを送信しようとしています。これを実現するために、私は次のコードを使用し、これはうまく動作しますがHTTP POSTでos.Stdinをメモリにロードせずに送信

func newfileUploadRequest(uri string) (*http.Request, error) { 

    body := new(bytes.Buffer) 
    writer := multipart.NewWriter(body) 
    part, err := writer.CreateFormFile("file", "file") 
    if err != nil { 
     return nil, err 
    } 
    io.Copy(part, os.Stdin) 

    err = writer.Close() 
    if err != nil { 
     return nil, err 
    } 

    request, err := http.NewRequest("POST", uri, body) 
    if err != nil { 
     return nil, err 
    } 
    request.Header.Set("Content-Type", writer.FormDataContentType()) 
    return request, nil 
} 


func main() { 
    r, err := newfileUploadRequest("http://localhost:8080/") 
    if err != nil { 
     panic(err) 
    } 

    client := &http.Client{} 
    resp, err := client.Do(r) 
    if err != nil { 
     panic(err) 
    } 
    body, err := ioutil.ReadAll(resp.Body) 
    if err != nil { 
     panic(err) 
    } 
    print(string(body)) 
} 

を、それはPOSTリクエストが送信される前にio.Copyは、ファイル全体をメモリにコピーします私の理解です。大きなファイル(複数のGB)は問題を作成します。これを防ぐ方法はありますか?私はthisを見つけましたが、単にio.Copyを使用すると言います。

答えて

2
あなたが io.Pipeとゴルーチンを使用してメモリ内のデータのコピーを回避することができ

そのファイルからパイプへのコピー:

func newfileUploadRequest(uri string) (*http.Request, error) { 
    r, w := io.Pipe() 
    writer := multipart.NewWriter(w) 
    go func() { 
    part, err := writer.CreateFormFile("file", "file") 
    if err != nil { 
     w.CloseWithError(err) 
     return 
    } 
    _, err = io.Copy(part, os.Stdin) 
    if err != nil { 
     w.CloseWithError(err) 
     return 
    } 
    err = writer.Close() 
    if err != nil { 
     w.CloseWithError(err) 
     return 
    } 
    }() 

    request, err := http.NewRequest("POST", uri, r) 
    if err != nil { 
    return nil, err 
    } 
    request.Header.Set("Content-Type", writer.FormDataContentType()) 
    return request, nil 
} 
1

使用io.Pipe()からhttps://golang.org/pkg/io/#Pipe

あなたはゴルーチンを使用する必要がありますが、やるにはあまりにも難しいことではありません。具体的な例が必要な場合は、コメントを残して、私はあなたのために1つを得るでしょう。

関連する問題