从HTTP请求读取图像';围棋中的尸体
我正在玩围棋(有史以来第一次),我想建立一个工具,从互联网上检索图像并剪切它们(甚至调整大小),但我在第一步就被卡住了从HTTP请求读取图像';围棋中的尸体,http,go,Http,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/int
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 */
}
我可以请求一个图像(让我们使用谷歌徽标),并得到它的种类和大小
事实上,我只是在重新编写图像(将其视为玩具“代理”),设置内容长度和内容类型,然后写回字节片,但我在某个地方弄错了。查看在Chromium 12.0.742.112(90304)上渲染的最终图像的外观:
我还检查了下载的文件,它是一个7007字节的PNG图像。如果我们查看请求,它应该正常工作:
获取/剪切HTTP/1.1用户代理: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.1200正常
内容长度:7007
内容类型:image/png
日期:2011年12月27日星期二19:51:53 GMT [巴布亚新几内亚数据] 你认为我做错了什么 免责声明:我正在搔痒,所以可能我使用了错误的工具:)无论如何,我可以在Ruby上实现它,但在我想尝试之前
更新:仍然抓痒,但。。。我认为这将是一个很好的侧面项目,所以如果它没有用处,我就打开它,至少有人可以通过开发它所使用的引用找到有用的东西。它们是给我的。我尝试了你的代码,注意到你提供的图像大小正确,但文件中超过某一点的内容都是0x00 回顾历史。需要记住的重要一点是,读取的字节数不超过您请求的字节数。它可以读取更少的内容,并且不会返回错误。(您也应该检查错误,但这不是问题。) 如果要确保缓冲区已完全满,请使用io.ReadFull。在这种情况下,只需使用io.copy复制读取器的全部内容就更简单了 记住关闭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,您只需要修复导入
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!")
}
瞧
这将使图像存储在数据中
一旦你有了它,你可以解码它,裁剪它,并返回到浏览器
希望这有帮助。我稍后会检查这一点。您所说的看起来是对的(我不认为图像中可能有0x0字节)。谢谢io.Copy无法按预期工作。请求在写入头之后被截断,我没有发现任何错误。无论如何,我用ReadFull解决了这个问题:如果你愿意,用我使用的方法编辑你的解决方案,仅供参考。我接受你的回答,因为你指出了正确的方向。谢谢很抱歉,有一个输入错误导致它无法工作(req和reqImg混淆)。我已经修复了代码,它与io.Copy.Oops一起工作,我也没有看到它。我确信这是一个要求。关于变量命名的一点经验:)应该是imgReq。