2017-05-24 16 views
2

に大きな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)ためColdFusion CFML Reference状態:

注: このアクションはファイルをローカル変数スコープの変数に読み込みます。ログなどの大きなファイルでは使用できません。サーバーを停止させる可能性があるためです。

FileReadBinary(filepath)を使用しないでください。大きな(0.5 - 1Tb)ファイルをアップロードするにはどうすればよいですか?

+1

とにかくWebインターフェイスから大きなファイルを読み込んではいけません。リクエストはアップロードされるまでに時間切れになります。要求のタイムアウトをどれくらい長くしても問題ありません.FTPサーバーにファイルをアップロードしたり、CFの外にファイルをアップロードしたり、他のプロセスでOracleにロードするなど、さまざまな解決策が必要なようです。 –

+1

私はそれが一般的な使用法ではないことに同意しますが、必ず失敗するとは限りません。私はWebリクエストに対して数百Mbytesの回答を出しているアプリケーションを開発していますが、うまくいきます。もちろん、クライアントとサーバーは同じLANにありますが、この場合は同じであると思います。 – Galcoholic

答えて

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がメモリ不足の例外をスローします)。
1

Javaを使用する場合、Blobフィールドを埋めるためにPreparedStatementにInputStreamオブジェクトを渡すことができます。追加するこの、例外処理や他のすべてのもののような何か:

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がメモリにファイル全体を読み込むバッファを使用してそれを行うには、ないと思います。

関連する問題