我有一个简单的(示例)脚本将文件上传到数据库(Oracle,如果重要的话):
<cfscript>
param string filename;
if ( FileExists( filename ) )
{
result = new StoredProc(
datasource = "ds",
procedure = "FILE_UPLOAD",
result = "NA",
parameters = [
{ value = FileReadBinary( filename ), type = "in", cfsqltype = "CF_SQL_BLOB" }
]
).execute();
}
</cfscript>
然而,FileReadBinary( filepath )
的{{3}}州:
注意: 此操作将文件读入本地变量范围中的变量。它不适用于大型文件,例如日志,因为它们可以关闭服务器。
如果我不使用FileReadBinary( filepath )
,我应该如何上传大型(0.5 - 1Tb)文件?
答案 0 :(得分:1)
如果使用Java是一个选项,则可以将InputStream对象传递给PreparedStatement以填充Blob字段。像这样的事情,异常处理和所有其他要添加的东西:
Connection con = someDataSource.getConnection();
String sql = "INSERT INTO MY_TABLE(MY_BLOB) VALUES(?)";
PreparedStatement ps = con.prepareStatement(sql);
InputStream fis = new FileInputStream("MyBigFile.big");
ps.setBlob(1, fis);
ps.executeUpdate();
我认为Java会使用缓冲区来完成,而不是将整个文件加载到内存中。
答案 1 :(得分:1)
根据@Galcoholic的建议,您可以使用基础Java类并使用CallableStatement.setBlob( int, InputStream )
:
<cfscript>
param string filename;
// Get the necessary Java classes:
Files = createObject( 'java', 'java.nio.file.Files' );
Paths = createObject( 'java', 'java.nio.file.Paths' );
// Do not timeout the request
setting requesttimeout = 0;
try {
input = Files.newInputStream( Paths.get( filename, [] ), [] );
connection = createObject( 'java', 'coldfusion.server.ServiceFactory' )
.getDataSourceService()
.getDataSource( 'ds' )
.getConnection()
.getPhysicalConnection();
statement = connection.prepareCall( '{call FILE_UPLOAD(?)}' );
statement.setBlob( JavaCast( 'int', 1 ), input );
statement.executeUpdate()
}
finally
{
if ( isDefined( "statement" ) )
statement.close();
if ( isDefined( "connection" ) )
connection.close();
}
</cfscript>
注意:
VARARGS
参数必须作为数组传递(或者没有其他参数的空数组)。JavaCast( 'int', value )
。coldfusion.util.MemorySemaphore
在解析脚本之前处理上传时会抛出内存不足的异常。)