2013-07-12 5 views
2

Я пытаюсь составить изображение в памяти и отправить его через http.ResponseWriter, не касаясь файловой системы.Правильное использование os.NewFile в Go

Я использую следующую команду, чтобы создать новый файл:

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 правильно. Может кто-то указать мне верное направление? Альтернативные предложения о том, как правильно выполнять манипуляции с файлами в памяти, приветствуются.

ответ

3

Пожалуйста, подробно читать документации NewFile. NewFile делает не Создайте новый файл, совсем нет! Он устанавливает Go os.File, который обертывает существующий файл с заданным файловым дескриптором (0 в вашем случае, который, как я думаю, является stdin).

Обслуживание изображений без файлов намного проще: просто скопируйте свое изображение в свой ResponseWriter. Для этого нужны интерфейсы. Не нужно писать в ome magic «в файле памяти», нет необходимости читать его с помощью ReadAll, просто и просто: напишите ответ.

+0

Я действительно искал в поисках интерфейса, который я мог бы легко удовлетворить для png.Encode раньше, но полностью пропустил очевидный и простой подход к прямому написанию ответа. Благодаря! – patrickn

5

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() 
+0

Да, изменил мой ответ соответствующим образом. –

+0

+1 для отображения примера «в файле памяти» для тех, кому это может понадобиться в будущем - в моем случае я просто хотел написать его непосредственно в ответ. И вы, и Фолькер верны, но он был прав первым. ;) – patrickn

+0

Прохладный. Полезная информация. –

Смежные вопросы