繁体   English   中英

从Go中的HTTP请求主体读取图像

[英]Reading image from HTTP request's body in Go

我正在玩Go(有史以来第一次),我想建立一个工具来从互联网上检索图像并切割它们(甚至调整大小)但我仍然坚持第一步。

package main

import (
  "fmt"
  "http"
)

var client = http.Client{}

func cutterHandler(res http.ResponseWriter, req *http.Request) {
  reqImg, err := client.Get("http://www.google.com/intl/en_com/images/srpr/logo3w.png")
  if err != nil {
    fmt.Fprintf(res, "Error %d", err)
    return
  }
  buffer := make([]byte, reqImg.ContentLength)
  reqImg.Body.Read(buffer)
  res.Header().Set("Content-Length", fmt.Sprint(reqImg.ContentLength)) /* value: 7007 */
  res.Header().Set("Content-Type", reqImg.Header.Get("Content-Type")) /* value: image/png */
  res.Write(buffer)
}

func main() {
  http.HandleFunc("/cut", cutterHandler)
  http.ListenAndServe(":8080", nil) /* TODO Configurable */
}

我可以请求一张图片(让我们使用Google徽标)并获得它的种类和尺寸。

实际上,我只是重新编写图像(将其视为玩具“代理”),设置Content-Length和Content-Type并将字节切片写回来,但我在某处弄错了。 看看它在Chromium 12.0.742.112(90304)上呈现的最终图像的外观:

怪诞的结果

我还检查了下载的文件,它是一个7007字节的PNG图像。 如果我们查看请求,它应该正常工作:

获取/削减HTTP / 1.1
User-Agent:curl / 7.22.0(i486-pc-linux-gnu)libcurl / 7.22.0 OpenSSL / 1.0.0e zlib / 1.2.3.4 libidn / 1.23 libssh2 / 1.2.8 librtmp / 2.3
主持人:127.0.0.1:8080
接受: /

HTTP / 1.1 200好的
内容长度:7007
内容类型:image / png
日期:2011年12月27日星期二19:51:53 GMT

[PNG数据]

你觉得我在这里做错了什么?

免责声明:我正在抓挠自己的痒,所以我可能正在使用错误的工具:)无论如何,我可以在Ruby上实现它,但在此之前我想尝试一下Go。

更新:仍然有点痒但是......我认为这将是一个很好的侧面项目所以我打开它https://github.com/imdario/go-lazor如果它没用,在至少有人可以通过用于开发它的引用找到有用的东西。 他们是给我的。

我尝试了你的代码并注意到你所服务的图像大小合适,但文件的内容超过了某一点都是0x00。

查看io.Reader文档 要记住的重要一点是,去读给你要求的字节数。 它可以读取更少,没有返回错误。 (您也应该检查错误,但这不是问题。)

如果要确保缓冲区已满,请使用io.ReadFull。 在这种情况下,使用io.Copy复制Reader的全部内容更为简单。

记住关闭HTTP请求主体也很重要。

我会用这种方式重写代码:

package main

import (
    "fmt"
    "http"
    "io"
)

var client = http.Client{}

func cutterHandler(res http.ResponseWriter, req *http.Request) {
    reqImg, err := client.Get("http://www.google.com/intl/en_com/images/srpr/logo3w.png")
    if err != nil {
        fmt.Fprintf(res, "Error %d", err)
        return
    }
    res.Header().Set("Content-Length", fmt.Sprint(reqImg.ContentLength))
    res.Header().Set("Content-Type", reqImg.Header.Get("Content-Type"))
    if _, err = io.Copy(res, reqImg.Body); err != nil {
        // handle error
    }
    reqImg.Body.Close()
}

func main() {
    http.HandleFunc("/cut", cutterHandler)
    http.ListenAndServe(":8080", nil) /* TODO Configurable */
}

我觉得你去服务的东西太快了。

专注于第一步, 下载图像

这里有一个小程序可以将该图像下载到内存中。
它适用于我的2011-12-22每周版本,对于r60.3你只需要gofix导入。

package main

import (
    "log"
    "io/ioutil"
    "net/http"
)

const url = "http://www.google.com/intl/en_com/images/srpr/logo3w.png"

func main() {
    // Just a simple GET request to the image URL
    // We get back a *Response, and an error
    res, err := http.Get(url)

    if err != nil {
        log.Fatalf("http.Get -> %v", err)
    }

    // We read all the bytes of the image
    // Types: data []byte
    data, err = ioutil.ReadAll(res.Body)

    if err != nil {
        log.Fatalf("ioutil.ReadAll -> %v", err)
    }

    // You have to manually close the body, check docs
    // This is required if you want to use things like
    // Keep-Alive and other HTTP sorcery.
    res.Body.Close()

    // You can now save it to disk or whatever...
    ioutil.WriteFile("google_logo.png", data, 0666)

    log.Println("I saved your image buddy!")
}

瞧!

这将把图像存入data内存。
完成后,您可以对其进行解码,裁剪并返回浏览器。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM