1

我正在尝试在内存中编写图像并通过 http.ResponseWriter 将其发送出去,而无需接触文件系统。

我使用以下内容创建一个新文件:

file := os.NewFile(0, "temp_destination.png")

但是,我似乎无法对这个文件做任何事情。这是我正在使用的函数(在 http.HandleFunc 中调用,它只是将文件的字节发送到浏览器),它旨在在临时文件上绘制一个蓝色矩形并将其编码为 PNG:

func ComposeImage() ([]byte) {
    img := image.NewRGBA(image.Rect(0, 0, 640, 480))
    blue := color.RGBA{0, 0, 255, 255}
    draw.Draw(img, img.Bounds(), &image.Uniform{blue}, image.ZP, draw.Src)

    // in memory destination file, instead of going to the file sys
    file := os.NewFile(0, "temp_destination.png")

    // write the image to the destination io.Writer
    png.Encode(file, img)

    bytes, err := ioutil.ReadAll(file)
    if err != nil {
        log.Fatal("Couldn't read temporary file as bytes.")
    }

    return bytes
}

如果我删除png.Encode调用,只返回文件字节,服务器就会挂起并且永远不做任何事情。

留下png.Encode调用会导致文件字节(编码,包括我希望看到的一些 PNG 块)被吐出到 stderr/stdout(我不知道是哪个)并且服务器无限期挂起。

我假设我只是没有正确使用 os.NewFile 。谁能指出我正确的方向?欢迎提供有关如何正确执行内存文件操作的替代建议。

4

2 回答 2

6

os.NewFile是大多数人永远不会直接使用的低级功能。它采用已经存在的文件描述符(文件的系统表示)并将其转换为*os.File(Go 的表示)。

如果您不希望图片接触您的文件系统,请完全远离 os 包。只需将您的 ResponseWriter 视为 io.Writer 并将其传递给png.Encode.

png.Encode(yourResponseWriter, img)

如果您坚持写入“内存文件”,我建议使用 bytes.Buffer:

buf := new(bytes.Buffer)
png.Encode(buf, img)
return buf.Bytes()
于 2013-07-12T00:23:37.443 回答
5

请详细阅读 NewFile 文档。NewFile 不会创建新文件,根本不会!它设置了一个 Go os.File,它使用给定的文件描述符(在您的情况下为 0,我认为是 stdin)围绕现有文件。

提供没有文件的图像要容易得多:只需将图像编码到 ResponseWriter 即可。这就是接口的用途。无需写入 ome 魔术“内存文件”,无需使用 ReadAll 将其读回,简单明了:写入您的回复。

于 2013-07-12T00:26:09.010 回答