#coldfusion #coldfusion-9
#coldfusion #coldfusion-9
Вопрос:
У меня есть сервис на сервере Coldfusion 9, который создает для нас графические баннеры «на лету». Отдельная машина должна сохранять эти файлы с чем-то вроде:
wget http://myserver.com/services/local/bannerCreator/250x250-v3.cfm?prodID=3amp;percentSaving=19
Проблема в том, что я не могу придумать, как заставить coldfusion записывать двоичные данные без использования временного файла. На данный момент изображение отображается просто как тег изображения, подобный этому:
<cfimage action = "writeToBrowser" source="#banner#" width="#banner.width#" height="#banner.height#" />
Есть идеи? Или я должен просто использовать временный файл?
Ответ №1:
Я не могу протестировать, потому что вы не даете никакого примера кода для того, как генерируются ваши изображения, но вы пробовали что-нибудь в этом роде?
<cfcontent reset="true" variable="#imageData#" type="image/jpg" />
Обновление: Итак, я пошел дальше и создал свой собственный образ; Я предполагаю, что вы делаете что-то подобное. У меня это работает идеально:
<cfset img = imageNew("",200,200,"rgb","red") />
<cfcontent variable="#toBinary(toBase64(img))#" type="image/png" reset="true" />
Это работает без записи в файл и без использования виртуальной файловой системы («ramdisk»)
Комментарии:
1. К вашему сведению: нет необходимости явно устанавливать для атрибута reset значение
true
, потому чтоtrue
это значение по умолчанию.
Ответ №2:
Если у вас есть двоичные байты файла / изображения, вы можете заменить выходной буфер его содержимым следующим образом:
<cfscript>
// eg. this is how you get a file as a binary stream
// var fileBytes = fileReadBinary( '/path/to/your/file.jpg' );
// get the http response
var response = getPageContext().getFusionContext().getResponse();
// set the appropriate mime type
response.setHeader( 'Content-Type', 'image/jpg' );
// replace the output stream contents with the binary
response.getOutputStream().writeThrough( fileBytes );
// leave immediately to ensure no whitespace is added
abort;
</cfscript>
В значительной степени то, что <cfcontent>
делает, когда вы используете reset="true"
Преимущество этого метода перед <cfcontent>
заключается в том, что мы можем записать его внутри наших cfcs на основе cfscript.
Ответ №3:
Я нашел решение выше
<cfcontent variable="#toBinary(toBase64(img))#" type="image/png" reset="true" />
для меня это не совсем работает.
Установка type=»image / png» — это просто установка mime-типа ответа. Я не думаю, что это обязательно кодирование изображения в формате PNG. Таким образом, генерация прозрачного png (тип изображения «argb») давала мне странные цвета по сравнению с <cfimage action = "writeToBrowser"...>
методом.
Я подумал, что каким-то образом мне нужно явно закодировать данные изображения в формате PNG и напрямую выводить двоичные данные.
Немного покопавшись в базовой java, я придумал это, которое пока, кажется, работает для меня.
В этом примере отображается прозрачный png-файл с черным кругом.
<!--- create the image and draw it --->
<cfset img = ImageNew("", 23, 23, "argb")>
<cfset ImageSetDrawingColor(img, "black")>
<cfset ImageDrawOval(img, 0, 0, 21, 21, true)>
<!--- get the response object --->
<cfset response = getPageContext().getFusionContext().getResponse()>
<!--- set the response mime type --->
<cfset response.setHeader('Content-Type', 'image/png')>
<!--- get the underlying image data --->
<cfset bImage = ImageGetBufferedImage(img)>
<!--- get the magical object to do the png encoding --->
<cfset ImageIO = createObject("java", "javax.imageio.ImageIO")>
<!--- encode the image data as png and write it directly to the response stream --->
<cfset ImageIO.write(bImage, "png", response.getResponse().getOutputStream())>
Я надеюсь, что это кому-то поможет!
Комментарии:
1. Правильно,
cfcontent
только задаетContent-Type
заголовок (и необязательно возвращает содержимое файла или переменной). Не предполагается изменять содержимое. Какой код выдал вам «нечетные цвета по сравнению сwriteToBrowser
«?2. Я получил нечетные цвета с помощью этого кода, Ли: <cfset img = imageNew(«»,1,1, «argb»,»»») /> <cfcontent variable=»#toBinary(toBase64(img))#» type=»image /png» reset =»true» /> Спасибо, Росс!
Ответ №4:
Уберите атрибуты height и width и добавьте атрибут format:
<cfimage action = "writeToBrowser" source="#banner#" format="png" />
wget должен учитывать перенаправление на физический файл, который CF создает в папке CFFileServlet, но если этого не происходит, есть флаг, который вы можете установить, чтобы сделать это --max-redirect=10
.
И, как вы предлагаете, временный файл тоже будет работать. Просто запишите файл и используйте cfheader и cfcontent для его записи. Просто убедитесь, что имя временного файла более уникально.
<cfimage action="write" destination="tempfile.png" source="#banner#" format="png" />
<cfheader name="content-disposition" value="attachment; filename=banner.png" />
<cfcontent file="tempfile.png" deletefile="true" type="image/png" />
Ответ №5:
Я делаю аналогичную вещь, и вам нужно объединить использование тегов и cfscript. Существуют функции изображения, которые требуются. Доступно множество функций изображения, если у вас есть изображение в памяти в качестве переменной. Вы можете загрузить изображение в память, используя CFFILE или CFHTTP, или несколькими другими способами.
В моем случае я считываю файл изображения в память, используя тег CFIMAGE, затем обрабатываю его с помощью функций изображения CFSCRIPT, добавляя текст внизу, затем выводя полученное изображение в формате .png (или .jpg, если вы предпочитаете) в браузере. Единственный файл, хранящийся на сервере, — это исходный файл изображения. В вашем случае вместо чтения в изображении вы бы вызвали его, используя тег cfhttp, как вы уже делаете. Вот мой код:
<!---Get the image for processing ...--->
<cfimage action="read" source="#application.approotABS#webcamwebcam.jpg" name="CamImage" />
<!--- prepare the text for overlay --->
<cfscript>
attr=structNew();
attr.font = "Arial";
attr.size = 15;
ImageSetDrawingColor(CamImage, "white");
ImageDrawText(CamImage, 'LIVE FROM STUDIO 1', 18,(ImageGetHeight(CamImage)-54), attr);
ImageDrawText(CamImage, '#ShowOnNow.showname#', 18,(ImageGetHeight(CamImage)-36), attr);
ImageDrawText(CamImage, datestring,18,(ImageGetHeight(CamImage)-18), attr);
</cfscript>
<!--- further down the page, output the manipulated image: ---->
<div class="webcam">
<cfimage action="writeToBrowser" source="#Camimage#" >
</div>
Вы можете увидеть это в действии на http://hawkesburyradio.com.au/index.cfm?pid=111538
(Я использую CF9 с Windows Server)