簡體   English   中英

如何接收流式傳輸的HTTP響應

[英]How to receive HTTP Response for streaming

當使用Go拋出HTTP請求並接收響應時,我想在流式傳輸時收到響應,考慮到ResponseBody很大(1 GB或更多)的情況。

resp, err: = http.Client.Do(req)

在這種情況下,如果身體很大,我無法讀取標題,我不知道響應的狀態。 有什么解決方案嗎?

(編輯:如果您無法從響應中獲取“Content-length”標頭,則您正在點擊的Web服務可能不會返回該標頭。在這種情況下,無法知道響應主體的長度沒有完全讀取。您可以通過刪除在響應中設置Content-length標頭的行來模擬以下示例中的內容。)

標准的Go net/http包可以很好地處理大型響應。 這是一個自包含的示例來演示:

// Start a mock HTTP server that returns 2GB of data in the response. Make a
// HTTP request to this server and print the amount of data read from the
// response.
package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "strings"
    "time"
)

const oneMB = 1024 * 1024
const oneGB = 1024 * oneMB
const responseSize = 2 * oneGB

const serverAddr = "localhost:9999"

func startServer() {
    // Mock HTTP server that always returns 2GB of data
    go http.ListenAndServe(serverAddr, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
        w.Header().Set("Content-length", fmt.Sprintf("%d", responseSize))

        // 1MB buffer that'll be copied multiple times to the response
        buf := []byte(strings.Repeat("x", oneMB))

        for i := 0; i < responseSize/len(buf); i++ {
            if _, err := w.Write(buf); err != nil {
                log.Fatal("Failed to write to response. Error: ", err.Error())
            }
        }
    }))

    // Some grace period for the server to start
    time.Sleep(100 * time.Millisecond)
}

func main() {
    startServer()

    // HTTP client
    req, err := http.NewRequest("GET", "http://"+serverAddr, nil)
    if err != nil {
        log.Fatal("Error creating HTTP request: ", err.Error())
    }

    client := http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal("Error making HTTP request: ", err.Error())
    }

    // Read the response header
    fmt.Println("Response: Content-length:", resp.Header.Get("Content-length"))

    bytesRead := 0
    buf := make([]byte, oneMB)

    // Read the response body
    for {
        n, err := resp.Body.Read(buf)
        bytesRead += n

        if err == io.EOF {
            break
        }

        if err != nil {
            log.Fatal("Error reading HTTP response: ", err.Error())
        }
    }

    fmt.Println("Response: Read", bytesRead, "bytes")
}

如果它太大,你不會想要在內存中讀取整個響應。 將其寫入臨時文件,然后進行處理。

如果您正在尋找可靠的選項,以便在網絡不可靠時可靠地執行此操作,請查找“HTTP范圍請求”,您可以使用該“范圍請求”恢復部分下載的數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM