将URL中的图像保存为Blob对象。

huangapple go评论186阅读模式
英文:

Save an image from url to blob

问题

我可以将一个来自URL的图像下载到文件中,如这里所示:

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "os"
  7. "strings"
  8. )
  9. var (
  10. fileName string
  11. fullUrlFile string
  12. )
  13. func main() {
  14. fullUrlFile = "https://i.imgur.com/m1UIjW1.jpg"
  15. r, e := http.Get(fullUrlFile)
  16. if e != nil {
  17. panic(e)
  18. }
  19. defer r.Body.Close()
  20. buildFileName()
  21. // 创建目标文件
  22. f, e := os.Create(fileName) // "m1UIjW1.jpg";
  23. if e != nil {
  24. panic(e)
  25. }
  26. defer f.Close()
  27. // 将内容填充到目标文件中
  28. n, e := f.ReadFrom(r.Body)
  29. if e != nil {
  30. panic(e)
  31. }
  32. fmt.Println("文件大小:", n)
  33. }
  34. func buildFileName() {
  35. fileUrl, e := url.Parse(fullUrlFile)
  36. if e != nil {
  37. panic(e)
  38. }
  39. path := fileUrl.Path
  40. segments := strings.Split(path, "/")
  41. fileName = segments[len(segments)-1]
  42. println(fileName)
  43. }

但是在我的应用程序中,我希望直接将图像保存为blob到indexedDB中,在JavaScript中可以这样做:

  1. // 获取blob
  2. // 创建XHR
  3. var xhr = new XMLHttpRequest(),
  4. blob;
  5. xhr.open("GET", "elephant.png", true);
  6. // 将responseType设置为blob
  7. xhr.responseType = "blob";
  8. xhr.addEventListener("load", function () {
  9. if (xhr.status === 200) {
  10. console.log("图像已检索");
  11. // 作为响应的文件
  12. blob = xhr.response;
  13. // 将接收到的blob放入IndexedDB
  14. transaction.objectStore("elephants").put(blob, "image");
  15. }
  16. }, false);
  17. // 发送XHR
  18. xhr.send();

我理解blob只是一个[]byte,所以我尝试将图像下载代码中从r.Body读取的内容转换为[]byte,如下所示:

  1. buf := new(bytes.Buffer)
  2. buf.ReadFrom(r.Body)
  3. blob := bytes.NewReader(buf.Bytes())
  4. dest, e := os.Create("test.jpg")
  5. n2, e := dest.ReadFrom(blob)
  6. fmt.Printf("字节数为:%d\n", n2)

但是它没有起作用!

问题是:我如何将从io.Reader读取的[]bytes转换为另一个可以保存在另一个目标中的io.Reader

英文:

I can download an image from url to file as shown here:

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "os"
  7. "strings"
  8. )
  9. var (
  10. fileName string
  11. fullUrlFile string
  12. )
  13. func main() {
  14. fullUrlFile = "https://i.imgur.com/m1UIjW1.jpg"
  15. r, e := http.Get(fullUrlFile)
  16. if e != nil {
  17. panic(e)
  18. }
  19. defer r.Body.Close()
  20. buildFileName()
  21. // Create distination
  22. f, e := os.Create(fileName) // "m1UIjW1.jpg"
  23. if e != nil {
  24. panic(e)
  25. }
  26. defer f.Close()
  27. // Fill distination with content
  28. n, e := f.ReadFrom(r.Body)
  29. if e != nil {
  30. panic(e)
  31. }
  32. fmt.Println("File size: ", n)
  33. }
  34. func buildFileName() {
  35. fileUrl, e := url.Parse(fullUrlFile)
  36. if e != nil {
  37. panic(e)
  38. }
  39. path := fileUrl.Path
  40. segments := strings.Split(path, "/")
  41. fileName = segments[len(segments)-1]
  42. println(fileName)
  43. }

But i my application, I want to save the image as blob directly from uel to indexedDB, in JavaScript this can be done as:

  1. // Get the blob
  2. // Create XHR
  3. var xhr = new XMLHttpRequest(),
  4. blob;
  5. xhr.open("GET", "elephant.png", true);
  6. // Set the responseType to blob
  7. xhr.responseType = "blob";
  8. xhr.addEventListener("load", function () {
  9. if (xhr.status === 200) {
  10. console.log("Image retrieved");
  11. // File as response
  12. blob = xhr.response;
  13. // Put the received blob into IndexedDB
  14. transaction.objectStore("elephants").put(blob, "image");
  15. }
  16. }, false);
  17. // Send XHR
  18. xhr.send();

My understanding the the blob is nothing but a []byte, so I tried converting the r.Body read in the image downloading code to []byte as:

  1. buf := new(bytes.Buffer)
  2. buf.ReadFrom(r.Body)
  3. blob := bytes.NewReader(buf.Bytes())
  4. dest, e := os.Create("test.jpg")
  5. n2, e := dest.ReadFrom(blob)
  6. fmt.Printf("The number of bytes are: %d\n", n2)

But it did not work!

The question is: How can I convert []bytes read from an io.Reader to another io.Reader that I can save in another destination.

答案1

得分: 1

我找到了,它非常简单,可以使用以下两种方法之一:

方法一:

  1. var dest []byte
  2. blob := bytes.NewBuffer(dest)
  3. io.Copy(blob, r.Body)

方法二:

  1. var dest []byte
  2. blob := bytes.NewBuffer(dest)
  3. b, e := ioutil.ReadAll(r.Body)
  4. if e != nil {
  5. panic(e)
  6. }
  7. src := bytes.NewReader(b)
  8. io.Copy(blob, src)

在这两种情况下,一旦r.Body或者基于它创建的任何io.Writer被使用一次后,就会完全消耗掉。

现在我的代码变成了:

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "strings"
  10. )
  11. var (
  12. fileName string
  13. fullUrlFile string
  14. )
  15. func main() {
  16. fullUrlFile = "https://i.imgur.com/m1UIjW1.jpg"
  17. r, e := http.Get(fullUrlFile)
  18. if e != nil {
  19. panic(e)
  20. }
  21. defer r.Body.Close()
  22. buildFileName()
  23. // 创建 blob
  24. var dest []byte
  25. blob := bytes.NewBuffer(dest)
  26. io.Copy(blob, r.Body)
  27. add_to_database(blob)
  28. }
  29. func buildFileName() {
  30. fileUrl, e := url.Parse(fullUrlFile)
  31. if e != nil {
  32. panic(e)
  33. }
  34. path := fileUrl.Path
  35. segments := strings.Split(path, "/")
  36. fileName = segments[len(segments)-1]
  37. println(fileName)
  38. }
  39. func add_to_database(blob *bytes.Buffer){}

请注意,我只翻译了代码部分,其他内容不包括在内。

英文:

I found it, it was very simple, either using:

  1. var dest []byte
  2. blob := bytes.NewBuffer(dest)
  3. io.Copy(blob, r.Body)

or using:

  1. var dest []byte
  2. blob := bytes.NewBuffer(dest)
  3. b, e := ioutil.ReadAll(r.Body)
  4. if e != nil {
  5. panic(e)
  6. }
  7. src := bytes.NewReader(b)
  8. io.Copy(blob, src)

In both cases, once r.Body or any io.Writer created based on it, is valid for one time usage, after that it is consumed in full.

my code now became:

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "strings"
  10. )
  11. var (
  12. fileName string
  13. fullUrlFile string
  14. )
  15. func main() {
  16. fullUrlFile = "https://i.imgur.com/m1UIjW1.jpg"
  17. r, e := http.Get(fullUrlFile)
  18. if e != nil {
  19. panic(e)
  20. }
  21. defer r.Body.Close()
  22. buildFileName()
  23. // Create blob
  24. var dest []byte
  25. blob := bytes.NewBuffer(dest)
  26. io.Copy(blob, r.Body)
  27. add_to_database(blob)
  28. }
  29. func buildFileName() {
  30. fileUrl, e := url.Parse(fullUrlFile)
  31. if e != nil {
  32. panic(e)
  33. }
  34. path := fileUrl.Path
  35. segments := strings.Split(path, "/")
  36. fileName = segments[len(segments)-1]
  37. println(fileName)
  38. }
  39. func add_to_database(blob *bytes.Buffer){}

huangapple
  • 本文由 发表于 2021年11月18日 13:37:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/70015043.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定