6

我正在尝试在 Coldfusion 8 上使用 CFHTTP 将一个大的(600MB)二进制文件下载到服务器:

<cfhttp 
  method="get" 
  url="#fileURL#" 
  path="#filePath#" 
  file="#fileName#" 
  timeout="600" 
  getasbinary="auto"
>

它适用于较小的文件(100 多 MB),但对于较大的文件,我收到 Server 500 错误:“java.lang.OutOfMemoryError: Java heap space”。

该文件正在从 Dropbox 文件夹下载 - 因此唯一可用的选项是使用 HTTP GET。

有谁知道如何下载它,所以它不会杀死服务器或超时?

4

2 回答 2

14

您可以通过从 CF 代码调用 Java 来做到这一点。缓冲的输入和输出流分类旨在保存数据块,而不是整个数据,从而避免 OutOfMemory 错误。

getByteArray()是一个辅助方法,因为没有办法byte buf[]=new byte[1024];直接在 CF 中声明类似的东西。

在示例中更改sourcedestination变量。

例子

<cfset source = 'protocol://domain/path/to/file.ext'>
<cfset destination = getDirectoryFromPath(getCurrentTemplatePath()) & listlast(source, "/")>
<cffunction name="getByteArray" access="private" returnType="binary" output="no">
    <cfargument name="size" type="numeric" required="true"/>
    <cfset var emptyByteArray =
        createObject("java", "java.io.ByteArrayOutputStream").init().toByteArray()/>
    <cfset var byteClass = emptyByteArray.getClass().getComponentType()/>
    <cfset var byteArray =
        createObject("java","java.lang.reflect.Array").newInstance(byteClass, arguments.size)/>
    <cfreturn byteArray/>
</cffunction>

<cfscript>
uri = createObject("java", "java.net.URL").init(source);
uis = uri.openStream();
bis = createObject("java", "java.io.BufferedInputStream").init(uis);
fos = createObject("java", "java.io.FileOutputStream").init(destination);
bos = createObject("java", "java.io.BufferedOutputStream").init(fos);
buffer = getByteArray(1024);
len = bis.read(buffer);
while(len > 0) {
    bos.write(buffer,0,len);
    len = bis.read(buffer);
}
bos.close();
bis.close();
fos.close();
uis.close();
</cfscript>
于 2011-01-19T19:26:43.920 回答
2

问题是它太大了。ColdFusion 在将其写入磁盘之前将整个内容读入内存。

您最好使用其他方法来获取文件。wget 可以从命令行执行 http 请求。明智地使用 CFEXECUTE 可能是一个好方法。

于 2011-01-19T18:13:28.313 回答