我使用下面的代码将请求发送到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}
答案 0 :(得分:2)
您必须消耗请求的正文。
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
给出以下评论,
我现在在打印resp后看到有一个csv文本,但类型是 http.Response我必须处理golang.org/pkg/encoding/csv/#Reader 如何将resp转换为字符串以便读者能够阅读它,或者我 想念其他东西吗?
OP必须了解http响应主体实现了io.Reader
接口。
当http响应从服务器返回时,主体不会作为字节片[]byte
直接读入内存。
OP还应注意,csv.Reader
是一种对消耗io.Reader
的CSV编码内容进行解码的实现。在后台,它没有将文件的全部内容保存在内存中,而是读取解码一行并进一步进行操作所需的内容。
由于golang实现的这两个重要属性,是将响应主体阅读器连接到csv阅读器很容易并且很自然。
对于这个问题,io.Reader
是什么,OP必须弄清楚它是能够以最大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)
}
}
答案 1 :(得分:1)
最简单的方法是使用ioutil.ReadAll
方法读取整个正文。该主体实现了io.Reader
接口,因此您可以使用该主体完成所有您可以使用阅读器执行的操作。如mh-cbon在他的答案中所示,这包括将其输送到stdout。
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语句中一样轻松地将其转换为字符串。