将大型BLOB传递给存储过程

时间:2017-05-24 14:43:23

标签: oracle stored-procedures coldfusion blob

我有一个简单的(示例)脚本将文件上传到数据库(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)文件?

2 个答案:

答案 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>

注意:

  • 必须为Java方法提供每个参数;因此对于具有可变参数数量的方法,VARARGS参数必须作为数组传递(或者没有其他参数的空数组)。
  • ColdFusion数值不会被隐式强制转换为Java数字文字,因此需要JavaCast( 'int', value )
  • 错误处理不包含在上面的示例中。
  • 如果文件已上传,则管理控制台中的“发布数据的最大大小”和“请求节流内存”设置需要从默认大小增加到正在上载的文件大小的适当限制(否则coldfusion.util.MemorySemaphore在解析脚本之前处理上传时会抛出内存不足的异常。)