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

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

Save an image from url to blob

问题

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

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)
}

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

// 获取blob
// 创建XHR
var xhr = new XMLHttpRequest(),
    blob;

xhr.open("GET", "elephant.png", true);
// 将responseType设置为blob
xhr.responseType = "blob";

xhr.addEventListener("load", function () {
    if (xhr.status === 200) {
        console.log("图像已检索");
        
        // 作为响应的文件
        blob = xhr.response;

        // 将接收到的blob放入IndexedDB
        transaction.objectStore("elephants").put(blob, "image");
    }
}, false);
// 发送XHR
xhr.send();

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

	buf := new(bytes.Buffer)
	buf.ReadFrom(r.Body)
    blob := bytes.NewReader(buf.Bytes())

    dest, e := os.Create("test.jpg")
	n2, e := dest.ReadFrom(blob)
	fmt.Printf("字节数为:%d\n", n2)

但是它没有起作用!

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

英文:

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

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)
}

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

// Get the blob
// Create XHR
var xhr = new XMLHttpRequest(),
    blob;

xhr.open("GET", "elephant.png", true);
// Set the responseType to blob
xhr.responseType = "blob";

xhr.addEventListener("load", function () {
    if (xhr.status === 200) {
        console.log("Image retrieved");
        
        // File as response
        blob = xhr.response;

        // Put the received blob into IndexedDB
        transaction.objectStore("elephants").put(blob, "image");
    }
}, false);
// Send XHR
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:

	buf := new(bytes.Buffer)
	buf.ReadFrom(r.Body)
    blob := bytes.NewReader(buf.Bytes())

    dest, e := os.Create("test.jpg")
	n2, e := dest.ReadFrom(blob)
	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

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

方法一:

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

方法二:

	var dest []byte
	blob := bytes.NewBuffer(dest)
	b, e := ioutil.ReadAll(r.Body)
	if e != nil {
		panic(e)
	}
	src := bytes.NewReader(b)
	io.Copy(blob, src)

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

现在我的代码变成了:

package main

import (
	"bytes"
	"fmt"
	"io"
	"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()
	// 创建 blob
	var dest []byte
	blob := bytes.NewBuffer(dest)
	io.Copy(blob, r.Body)

    add_to_database(blob)
}

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)
}

func add_to_database(blob *bytes.Buffer){}

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

英文:

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

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

or using:

	var dest []byte
	blob := bytes.NewBuffer(dest)
	b, e := ioutil.ReadAll(r.Body)
	if e != nil {
		panic(e)
	}
	src := bytes.NewReader(b)
	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:

package main

import (
	"bytes"
	"fmt"
	"io"
	"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 blob
	var dest []byte
	blob := bytes.NewBuffer(dest)
	io.Copy(blob, r.Body)

    add_to_database(blob)
}
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)
}

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:

确定