在Go中正确使用os.NewFile

时间:2013-07-12 00:07:54

标签: go

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

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

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

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

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。谁能指出我正确的方向?关于如何正确执行内存中文件操作的替代建议是值得欢迎的。

2 个答案:

答案 0 :(得分:5)

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

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

png.Encode(yourResponseWriter, img)

如果你坚持写一个&#34;在内存文件&#34;,我建议使用bytes.Buffer:

buf := new(bytes.Buffer)
png.Encode(buf, img)
return buf.Bytes()

答案 1 :(得分:2)

请详细阅读NewFile文档。 NewFile 创建一个新文件,完全没有!它设置了一个Go os.File,它使用给定的文件描述符包装现有文件(在你的情况下为0,我认为是stdin)。

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