【问题标题】:http put server handling large fileshttp put 服务器处理大文件
【发布时间】:2019-07-26 00:55:57
【问题描述】:

请考虑这个code posted here,它处理http PUT 请求。它工作正常,文件小:

$ curl  -v http://192.168.1.10:9193/ -T red.tx
*   Trying 192.168.1.10...
* Connected to 192.168.1.10 (192.168.1.10) port 9193 (#0)
> PUT /red.tx HTTP/1.1
> Host: 192.168.1.10:9193
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 19697247
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Date: Fri, 26 Jul 2019 00:43:43 GMT
< Content-Length: 0
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host 192.168.1.10 left intact

但是 - 发送一个大于 1G 的大文件,它会耗尽内存。这是可以理解的,因为整个正文被读为contents, err := ioutil.ReadAll(r.Body)

runtime: out of memory: cannot allocate 536870912-byte block (537919488 in use)
fatal error: out of memory    
runtime stack:
runtime.throw(0x259a35, 0xd)
        /usr/lib/go-1.7/src/runtime/panic.go:566 +0x78
runtime.largeAlloc(0x1ffffe00, 0x10616f01, 0x10637afc)
        /usr/lib/go-1.7/src/runtime/malloc.go:776 +0xc8
runtime.mallocgc.func1()
        /usr/lib/go-1.7/src/runtime/malloc.go:669 +0x34
runtime.systemstack(0x10aa8200)
        /usr/lib/go-1.7/src/runtime/asm_arm.s:247 +0x80
runtime.mstart()
        /usr/lib/go-1.7/src/runtime/proc.go:1079

请告诉我读取 r.Body 并将其写入文件的正确方法。谢谢!

【问题讨论】:

  • 不要使用ioutil.ReadAll,因为它将整个Reader流读入内存,最好使用io.Copy,因为它会逐块进行

标签: go


【解决方案1】:

尝试将请求负载直接复制到文件中。

f, err := os.Create(temporaryFilename)
if err != nil {
    return err
}
defer f.Close()

_, err := io.Copy(f, r.Body)

如果您需要对复制的文件进行操作,只需操作创建的文件对象(在上面的示例中为 f)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 2012-04-25
    • 2018-03-25
    • 2016-09-14
    • 2020-09-10
    相关资源
    最近更新 更多