英文:
Save an image from url to file
问题
非常新手Go(我正在做的第一个简单项目)。
问题:如何从URL获取图像并将其保存到计算机上?
以下是我目前的代码:
package main
import (
"fmt"
"net/http"
"image"
"io/ioutil"
)
func main() {
url := "http://i.imgur.com/m1UIjW1.jpg"
// 不用担心错误
response, _ := http.Get(url)
defer response.Body.Close()
m, _, err := image.Decode(response.Body)
err = ioutil.WriteFile("/images/asdf.jpg", m, 0644)
}
然而,当我运行这段代码时,我得到了cannot use m (type image.Image) as type []byte in function argument
的错误。
我猜想我需要将image.Image(变量m
)转换为未定义数量的字节?这样做是正确的方法吗?
英文:
Very new to Go (first simple project I'm working on).
Question: How do I get an image from URL and then save it to my computer?
Here's what I have so far:
package main
import (
"fmt"
"net/http"
"image"
"io/ioutil"
)
func main() {
url := "http://i.imgur.com/m1UIjW1.jpg"
// don't worry about errors
response, _ := http.Get(url);
defer response.Body.Close()
m, _, err := image.Decode(response.Body)
error := ioutil.WriteFile("/images/asdf.jpg", m, 0644)
}
However, when I run this code, I get cannot use m (type image.Image) as type []byte in function argument
I'm assuming I have to convert image.Image (variable m
) into an undefined amount of bytes? Is that the correct way to go about this?
答案1
得分: 49
不需要解码文件。只需将响应主体复制到您打开的文件中。以下是修改后示例中的步骤:
response.Body
是一串数据流,实现了Reader
接口 - 这意味着您可以按顺序调用Read
方法,就像它是一个打开的文件一样。- 此处打开的文件实现了
Writer
接口。这是相反的操作 - 它是一个可以调用Write
方法的流。 io.Copy
将一个读取器和一个写入器“连接”起来,它会消耗读取器流并将其内容写入写入器。
这是 Go 语言中我最喜欢的特性之一 - 隐式接口。您不需要声明您正在实现一个接口,只需要实现它以在某个上下文中使用。这允许混合和匹配不需要了解其交互的其他代码的代码。
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
)
func main() {
url := "http://i.imgur.com/m1UIjW1.jpg"
// 不用担心错误
response, e := http.Get(url)
if e != nil {
log.Fatal(e)
}
defer response.Body.Close()
// 打开一个文件进行写入
file, err := os.Create("/tmp/asdf.jpg")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// 使用 io.Copy 将响应主体直接转储到文件中。这支持大文件
_, err = io.Copy(file, response.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("Success!")
}
希望对您有所帮助!
英文:
There is no need to decode the file. Simply copy the response body to a file you've opened. Here's the deal in the modified example:
response.Body
is a stream of data, and implements theReader
interface - meaning you can sequentially callRead
on it, as if it was an open file.- The file I'm opening here implements the
Writer
interface. This is the opposite - it's a stream you can callWrite
on. io.Copy
"patches" a reader and a writer, consumes the reader stream and writes its contents to a Writer.
This is one of my favorite things about go - implicit interfaces. You don't have to declare you're implementing an interface, you just have to implement it to be used in some context. This allows mixing and matching of code that doesn't need to know about other code it's interacting with.
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
)
func main() {
url := "http://i.imgur.com/m1UIjW1.jpg"
// don't worry about errors
response, e := http.Get(url)
if e != nil {
log.Fatal(e)
}
defer response.Body.Close()
//open a file for writing
file, err := os.Create("/tmp/asdf.jpg")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// Use io.Copy to just dump the response body to the file. This supports huge files
_, err = io.Copy(file, response.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("Success!")
}
答案2
得分: 7
以下是代码的中文翻译:
package main
import (
"io"
"net/http"
"os"
"fmt"
)
func main() {
img, _ := os.Create("image.jpg")
defer img.Close()
resp, _ := http.Get("http://i.imgur.com/Dz2r9lk.jpg")
defer resp.Body.Close()
b, _ := io.Copy(img, resp.Body)
fmt.Println("文件大小:", b)
}
这段代码是一个简单的Go语言程序,它从指定的URL下载一张图片,并将其保存到本地文件中。程序首先创建一个名为image.jpg
的文件,然后使用http.Get
函数从指定的URL获取图片的内容。接着,使用io.Copy
函数将获取到的内容写入到文件中。最后,程序输出文件的大小。
英文:
package main
import (
"io"
"net/http"
"os"
"fmt"
)
func main() {
img, _ := os.Create("image.jpg")
defer img.Close()
resp, _ := http.Get("http://i.imgur.com/Dz2r9lk.jpg")
defer resp.Body.Close()
b, _ := io.Copy(img, resp.Body)
fmt.Println("File size: ", b)
}
答案3
得分: 2
请尝试以下代码:
package main
import (
"fmt"
"net/http"
"net/url"
"os"
"strings"
)
var (
fileName string
fullUrlFile string
)
func main() {
fullUrlFile = "https://i.imgur.com/m1UIjW1.jpg"
r, e := http.Get(fullUrlFile)
if e != nil {
panic(e)
}
defer r.Body.Close()
buildFileName()
// 创建目标文件
f, e := os.Create(fileName) // "m1UIjW1.jpg";
if e != nil {
panic(e)
}
defer f.Close()
// 填充目标文件内容
n, e := f.ReadFrom(r.Body)
if e != nil {
panic(e)
}
fmt.Println("文件大小:", n)
}
func buildFileName() {
fileUrl, e := url.Parse(fullUrlFile)
if e != nil {
panic(e)
}
path := fileUrl.Path
segments := strings.Split(path, "/")
fileName = segments[len(segments)-1]
println(fileName)
}
希望对你有帮助!
英文:
Try this:
package main
import (
"fmt"
"net/http"
"net/url"
"os"
"strings"
)
var (
fileName string
fullUrlFile string
)
func main() {
fullUrlFile = "https://i.imgur.com/m1UIjW1.jpg"
r, e := http.Get(fullUrlFile)
if e != nil {
panic(e)
}
defer r.Body.Close()
buildFileName()
// Create distination
f, e := os.Create(fileName) // "m1UIjW1.jpg"
if e != nil {
panic(e)
}
defer f.Close()
// Fill distination with content
n, e := f.ReadFrom(r.Body)
if e != nil {
panic(e)
}
fmt.Println("File size: ", n)
}
func buildFileName() {
fileUrl, e := url.Parse(fullUrlFile)
if e != nil {
panic(e)
}
path := fileUrl.Path
segments := strings.Split(path, "/")
fileName = segments[len(segments)-1]
println(fileName)
}
答案4
得分: 1
你也可以使用ReadFrom
方法:
package main
import (
"net/http"
"os"
)
func main() {
r, e := http.Get("https://i.imgur.com/m1UIjW1.jpg")
if e != nil {
panic(e)
}
defer r.Body.Close()
f, e := os.Create("m1UIjW1.jpg")
if e != nil {
panic(e)
}
defer f.Close()
f.ReadFrom(r.Body)
}
https://golang.org/pkg/os#File.ReadFrom
英文:
You can also use the ReadFrom
method:
package main
import (
"net/http"
"os"
)
func main() {
r, e := http.Get("https://i.imgur.com/m1UIjW1.jpg")
if e != nil {
panic(e)
}
defer r.Body.Close()
f, e := os.Create("m1UIjW1.jpg")
if e != nil {
panic(e)
}
defer f.Close()
f.ReadFrom(r.Body)
}
答案5
得分: 0
response.Body
的类型是什么?如果它不是[]byte
类型,你应该将其转换为[]byte
类型,并将其写入磁盘。除非你有某种将数据视为图像的原因,否则没有必要使用image
类。只需将数据视为一系列字节,并将其写入磁盘即可。
英文:
What is the type of response.Body
? You should just convert that into a []byte
if it is not and write that to disk. There is no reason to use the image
class unless you have some reason to treat the data as an image. Just treat the data as a series of bytes and write it to the disk.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论