【问题标题】:How to read file content from an http.Request's response如何从 http.Request 的响应中读取文件内容
【发布时间】:2019-09-30 10:03:33
【问题描述】:

我使用下面的代码向 http 服务器发送请求。

服务器发送包含这些 http 标头的响应

Content-Disposition:[attachment;filename=somefilename.csv] 
Content-Type:[text/csv; charset=UTF-8]

如何继续检索随响应附加的文件的内容?

baseUrl := "Some url that i call to fetch csv file"

client := http.Client{}

resp, _ := client.Get(baseUrl)
defer resp.Body.Close()

fmt.Println(resp)

// &{200 OK 200 HTTP/2.0 2 0 map[Content-Disposition:[attachment;filename=somefilename.csv] Content-Type:[text/csv; charset=UTF-8] Date:[Mon, 30 Sep 2019 09:54:08 GMT] Server:[Jetty(9.2.z-SNAPSHOT)] Vary:[Accept]] {0xc000530280} -1 [] false false map[] 0xc000156200 0xc0000c26e0}

【问题讨论】:

  • 该文件不是此 HTTP 标头的一部分。
  • 他不知道自己在做什么。除非它可以被标记为重复,否则请帮助改进问题/响应而不是投接近票。

标签: go multipart content-disposition


【解决方案1】:

您必须使用请求的正文。

baseUrl := "Some url that i call to fetch csv file"

client := http.Client{}

resp, _ := client.Get(baseUrl)
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body) // this line.

fmt.Println(resp)

如果你必须处理多部分表单数据https://golang.org/pkg/net/http/#Request.FormFile

鉴于以下评论,

我现在在打印后看到有一个 csv 文本,但类型是 http.Response 我必须处理 golang.org/pkg/encoding/csv/#Reader 如何将 resp 转换为字符串以便读者能够阅读它,或者我 想念别的东西?

OP 必须了解 http 响应 Body 实现了 io.Reader 接口。 当 HTTP 响应从服务器返回时,正文不会作为字节切片 []byte 直接读入内存。

OP 还应注意,csv.Reader 是一种对使用io.Reader 的 CSV 编码内容进行解码的实现。在后台,它不会将文件的全部内容保存在内存中,它会读取解码一行所需的内容并继续进行。

由于 golang 实现的这两个重要属性,将响应正文阅读器连接到 csv 阅读器很容易和自然。

对于这个问题,io.Reader 是什么,OP 必须弄清楚它是能够通过 max len p 块读取字节流的任何东西。这个接口的唯一方法签名说明了这一点Read([]byte) (int, error)

此接口的设计方式是最大限度地减少消耗的内存和分配。

参考链接

说了这么多,最后的代码写的很简单,

package main

import (
    "encoding/csv"
    "fmt"
    "io"
    "log"
    "net/http"
)

func main() {
    baseUrl := "https://geolite.maxmind.com/download/geoip/misc/region_codes.csv"

    client := http.Client{}

    resp, err := client.Get(baseUrl)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    fmt.Println(resp)

    r := csv.NewReader(resp.Body)

    for {
        record, err := r.Read()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatal(err)
        }

        fmt.Println(record)
    }
}

【讨论】:

  • 我现在在打印 resp 后看到有一个 csv 文本但类型是 http.Response 我必须处理 golang.org/pkg/encoding/csv/#Reader 如何将 resp 转换为字符串才能让读者阅读它,还是我想念别的东西?
  • 查看我的答案
【解决方案2】:

最简单的方法是使用ioutil.ReadAll 方法读取整个正文。 body 实现了io.Reader 接口,所以你可以用 reader 做的所有事情都可以用 body 完成。这包括将其管道传输到标准输出,正如 mh-cbon 在他的回答中所显示的那样。

baseUrl := "Some url that i call to fetch csv file"

resp, err := http.Get(baseUrl)
if err != nil {
    // do something with the error
}
defer resp.Body.Close()

content, err := ioutil.ReadAll(resp.Body)
if err != nil {
    // do something with the error
}

fmt.Println(string(content))

请注意,我删除了client。简单的GET 调用不需要它。如果您需要更多配置,请使用 http.Client,就像您在示例中所做的那样。

另请注意,content 的类型为 []byte,但它可以很容易地转换为字符串,就像上面在 print 语句中所做的那样。

【讨论】:

  • 我很不高兴你提出了一个字符串转换,所以我更新了我的答案。
  • 是的,非常好!我试图给出最简单的答案,但也指出正文是io.Reader。对于大文件和流式传输,一次读取正文是一个坏主意……但要复杂得多——尤其是对于初学者。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 2016-11-02
  • 2020-08-28
  • 2013-01-23
  • 1970-01-01
相关资源
最近更新 更多