2011-12-27 10 views
1

私はGoで初めて遊んでいますが、インターネットから画像を取得して切り取る(サイズを変更する)ツールを作っていますが、最初のステップで固まっています。GoでのHTTP要求の本文から画像を読み取る

画像をリクエストして、その種類とサイズを取得できます(Googleロゴを使用します)。

確かに、Content-LengthとContent-Typeを設定してバイトスライスを書き戻していますが、どこかで間違ったイメージになってしまいました。それはクロム12.0.742.112(90304)の上にレンダリングされた最終画像をどのように見えるかを参照してください:

Grotesque result

また、私はダウンロードしたファイルをチェックし、それは、画像をPNG 7007バイトです。

GET /カットHTTP/1.1
のUser-Agent:カール/ 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 OK
を コンテンツの長さ:7007
のContent-Type:画像/ PNG
日:火、2011年12月27日午後七時51分53秒GMT

[PNGデータ]

あなたは私がここで間違ってやってるどう思いますか?

免責事項:私は自分のかゆみを掻いているので、間違ったツールを使用している可能性があります:)とにかく、私はRubyで実装できますが、前に試してみてください。

更新:まだ痒みを掻いていますが...これは良い側面のプロジェクトになると思いますので開けますhttps://github.com/imdario/go-lazor参考にならない場合、それを開発するために使用されます。彼らは私のためだった。

答えて

8

私はあなたのコードを試して、あなたが提供していたイメージが正しいサイズであることに気付きましたが、特定のポイントを過ぎたファイルの内容はすべて0x00でした。

io.Reader documentationを確認してください。覚えておくべき重要なことは、読んでまでまで要求したバイト数を読み取ることです。エラーを返さずに読み込み回数を減らすことができます。 (エラーもチェックする必要がありますが、これは問題ではありません)

バッファが完全にいっぱいであることを確認したい場合は、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 */ 
} 
+0

これを後で確認します。あなたが言ったことは正しいと思います(私はイメージの可能な0x0バイトではないと思いました)。ありがとう! –

+0

io.Copyが期待どおりに動作しません。ヘッダーを書き込んだ後に要求が切り詰められ、エラーは検出されません。 とにかく、私はReadFullで解決しました。https://gist.github.com/1528886必要に応じて、私が使ったものを使ってあなたのソリューションを編集してください。あなたが正しい方法を指摘したので、私はあなたの答えを受け入れます。ありがとう! –

+0

申し訳ありませんが、それが動作しない原因となるタイプミスがありました(reqとreqImgが混在しています)。私はコードを修正し、io.Copyで動作します。 –

7

私はあなたがパート物事を果たすに速すぎていったと思います。

最初のステップに焦点を合わせて、をダウンロードしてください。

ここでは、そのイメージをメモリにダウンロードする小さなプログラムがあります。
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!") 
} 

ボイラ!

これで、画像はdataのメモリに保存されます。
これを取得したら、デコードしてトリミングしてブラウザに返します。

これが役に立ちます。

関連する問題