Как получить временный путь к файлу, извлеченному с помощью CFHTTP в Coldfusion?

Я использую Coldfusion8 и мне нужно получить изображения с удаленного сервера, что я делаю следующим образом:

 <cfhttp timeout="45" throwonerror="no" url="#variables.testFilePath#" method="get" useragent="Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12" getasbinary="yes" result="variables.objGet">
 <cfset variables.objImage = ImageNew(variables.objGet.FileContent)>

Теперь мне нужно сохранить изображение на Amazon S3, но функция, которую я хочу использовать:

 <cfset result = s3.putObject(url.b,file.serverFile,file.contentType,'300',form.cacheControl,'30',form.acl,form.storageClass,form.keyName,GetTempDirectory())>

Требуется каталог, в котором можно найти мое сгенерированное изображение.

Вопрос.
Есть ли способ получить каталог файла изображения, извлеченного с помощью cfhttp, и преобразовать его в изображение с помощью imageNew? Или мне нужно сначала сохранить файл на диск? Мне также нужно изменить размер перед сохранением, поэтому я не смогу обойтись без предварительного сохранения на диск.

Спасибо за указатели!

EDIT:
У меня это работает так:

<!--- getAsBinary --->
<cfhttp timeout="45" 
    throwonerror="no" 
    url="#variables.testFilePath#" 
    method="get" 
    useragent="..."         
    getasbinary="yes" 
    result="objGet">

<!--- validate --->
<cfif len(variables.testFilePath) EQ 0>
    <cfset variables.errorCount = variables.errorCount+1>
    <cfset variables.failedLoads = "FILE NOT FOUND" >
<cfelse>
    <cfif len(objGet.Filecontent) EQ 0>
        <cfset variables.errorCount = variables.errorCount+1>
        <cfset variables.failedLoads = "COULD NOT LOAD IMAGE">
    <cfelseif NOT listfindnocase(variables.allow, variables.fileExt) >
        <cfset variables.errorCount = variables.errorCount+1>
        <cfset variables.failedLoads = "WRONG FILE TYPE">
    <cfelse>
        <cftry>
            <cfscript>
                objImage = ImageNew(objGet.FileContent);
                ImageSetAntialiasing(objImage,"on");
                <!--- resize/crop --->
                variables.keyName = Session.loginid & "_S_";
            </cfscript>
            <!--- convert modified image back to binary --->
            <cfset variables.filekey = toBase64( objImage )>
            <!--- pass to s3.cfc --->
            <cfset result = s3.putObject(variables.bucketName, variables.filekey, variables.contentType, variables.httptimeout, variables.cacheControl, variables.cacheDays, variables.acl, variables.storageClass, variables.keyName, variables.imageSrc, "true" )>
            <cfcatch>
                <cfset variables.errorCount = variables.errorCount+1>
                <cfset variables.failedLoads = "NO IMAGE">
            </cfcatch>
        </cftry>
    </cfif>

Мне нужно повторно преобразовать обрезанное изображение в двоичное, потому что s3.putobject в противном случае выполнит еще одно cffile action="readBinary" и прервется при попытке создать путь к файлу изображения (изображение все еще находится во временном состоянии) прямо здесь:

<cffile action="readBinary" file="#arguments.uploadDir##arguments.fileKey#" variable="binaryFileData">

Хотя я могу получить путь к временному файлу, используя этот trick и установить uploadDir не помогает, потому что документы CF говорят, что путь должен быть либо абсолютным путем, начинающимся с буквы диска, либо с косой чертой, иначе будет выбран временный каталог www-root.

В моем случае временный каталог www-root находился в C:/, в то время как временный файл CFFile-Servlet был в E:/, и относительный путь также не работал (файл не найден). Так как я не нашел способа перечитать образ из s3.cfc, теперь я конвертирую его обратно в двоичный формат перед вызовом S3.cfc. Я передаю еще один параметр (1/0), говорящий s3.cfc, что я уже отправляю бинарное изображение и нет необходимости его перечитывать.

Вот так:

<!--- if encoded is true, filekey already is the encoded image --->
<cfif arguments.encoded EQ "true">
    <!--- already sending binary image --->
    <cfset binaryFileData = arguments.fileKey>
<cfelse>
    <!--- Default --->
    <cffile action="readBinary" file="#arguments.uploadDir##arguments.fileKey#" variable="binaryFileData">
</cfif>

Я не уверен, что это самый разумный способ с точки зрения производительности, но, похоже, он работает довольно гладко. Комментарии приветствуются!


person frequent    schedule 10.08.2012    source источник


Ответы (3)


Я думаю, вы могли бы использовать атрибуты path и file вместо result. Сгенерируйте некоторый временный путь, используя GetTempDirectory() + CreateUUID(), извлеките и затем отпустите его. Кроме того, это может быть немного более эффективным с точки зрения использования памяти, чем извлечение содержимого в переменную, а затем запись в промежуточный файл.

person Sergey Galashyn    schedule 10.08.2012
comment
Один вопрос: будет ли это эффективный подход? Мне не пришлось бы очищать и не сохранять изображение в файл. - person frequent; 10.08.2012
comment
Извините, я не совсем понимаю, как этот подход можно использовать в вашем случае... Вам в основном нужно скачать файл и загрузить его в другое место. Более эффективным решением может быть использование чего-то вроде rsync (Unix). В случае использования Railo вы можете смонтировать ведро S3 как отображение и сохранить файл прямо там. Хотя не уверен, что это сработает. - person Sergey Galashyn; 10.08.2012
comment
ни используя Unix или Railo. Я буду с этим играться, но насколько я понимаю, я читаю файл и вместо того, чтобы сохранять его на диск, я записываю его в XML-буфер (будет в CFFileServelet), откуда я могу получить src, который мне нужен для вызова S3. - person frequent; 10.08.2012

Результат Cfhttp сохраняет данные в переменной памяти. ImageNew создает образ «ColdFusion», что означает, что он также находится только в памяти. Вам нужно будет сохранить его, чтобы сделать его физическим файлом для отправки либо в cfhttp, либо в imagewrite и т. д.

Не сохраняя его в физический файл, вы должны использовать cffile action = "writetobrowser", чтобы отправить его в браузер, но это в конечном итоге сохранит его во временном месте, чтобы браузер мог получить к нему доступ, но здесь это не принесет вам много пользы. считать.

http://livedocs.adobe.com/coldfusion/8/htmldocs/functions_h-im_34.html http://livedocs.adobe.com/coldfusion/8/htmldocs/Images_19.html

person Travis    schedule 10.08.2012

AmazonS3Client имеет метод putObject, который принимает InputStream, поэтому вы можете обернуть двоичные данные в ByteArrayInputStream и передайте его, не беспокоясь о резервном файле.

Что-то вроде этого:

<cfhttp method="get" url="#local.url#" result="local.httpResult" getAsBinary="true"/>
<cfif local.httpResult.statusCode eq "200 OK">
    <cfset var fileInputStream = createObject("java", "java.io.ByteArrayInputStream" ).init(local.httpResult.fileContent) />
    <cfset var objectMetadata = createObject("java", "com.amazonaws.services.s3.model.ObjectMetadata" ).init() />
    <cfset application.S3UTIL.s3Client.putObject("some.bucket", "folder/file.ext", local.fileInputStream, local.objectMetadata)/>
</cfif>
person Rupert Rawnsley    schedule 16.12.2015