2010-08-10 113 views
0

使用PHP,我試圖下載一個已經上傳到Oracle 10g數據庫的blob文件。我已經看到並模仿了我發現的大量例子。當我訪問該頁面時,出現一個文件下載對話框,允許我打開或保存。如果我點擊打開,媒體播放器會自動彈出,但不會檢索文件。如果我選擇保存,我總是會收到一條錯誤消息,指出「Internet Explorer無法打開此Internet站點,請求的站點不可用或無法找到,請稍後重試。」使用Oracle和PHP下載BLOB文件

下面是我的代碼,它非常簡單,非常像我找到的例子。

<?php 

header('Content-Disposition: attachment; filename='.$_GET['fileName']); 
header('Content-length: '.$_GET['fileSize']); 
header('Content-type: '.$_GET['mimeType']); 

require_once("Include/Application.php"); 

$connection = oci_connect ($userID, $password, $TNS); 

$phpCur = oci_new_cursor($connection); 
$stmt = oci_parse($connection, "BEGIN MOR.DOWNLOAD_ATTACHMENT (:morID, :attachmentType, :phpCur); END;"); 
oci_bind_by_name($stmt, ":morID", $_GET['morID'], -1); 
oci_bind_by_name($stmt, ":attachmentType", $_GET['attachmentType'], -1); 
oci_bind_by_name($stmt, "phpCur", $phpCur, -1, OCI_B_CURSOR); 
oci_execute($stmt); 
oci_free_statement($stmt); 

$output = ''; 
oci_execute($phpCur); 
while($row = oci_fetch_array($phpCur)) 
    $output .= $row['ATTACHMENT_BL']; 

oci_free_statement($phpCur); 

oci_close($connection); 

echo $output; 

exit; 

?> 
+1

'標題( '內容長度:'。$ _ GET [ '檔案大小']);' - 內容長度由GET參數確定,而不是blob數據的實際(字節)大小?聽起來不對。 – VolkerK 2010-08-10 16:03:41

+0

當文件上傳時,附件的大小存儲在一個單獨的字段中。在我打電話給這個頁面之前,我使用AJAX調用來獲取這些信息。我不知道這是否是標準做法,但據我瞭解,我需要提前知道文件大小,以便爲頭文件提供它。儘管現在我看到我的程序調用後有三個頭部語句,但我可以在下載BLOB的同時獲得這些信息。 – user39653 2010-08-10 16:55:39

回答

0

向腳本添加更多錯誤處理。任何oci *函數都可能失敗,然後後續步驟也會失敗。 documentation告訴你如果一個函數失敗和返回值將會發生什麼。例如。

返回值
返回一個連接標識符 或FALSE上錯誤。

如果您將Content-type標頭設置爲儘可能晚,即直接在第一個輸出之前,則可以發送包含某種錯誤消息的純文本或html。

<?php 
// error_reporting/ini_set: for testing purposes only. 
error_reporting(E_ALL); ini_set('display_errors', 1); 

require_once("Include/Application.php"); 

$connection = oci_connect ($userID, $password, $TNS); 
if (!$connection) { 
    die('database connection failed'); 
} 

$phpCur = oci_new_cursor($connection); 
if (!$phpCur) { 
    die('creating cursor failed'); 
} 

$stmt = oci_parse($connection, "BEGIN MOR.DOWNLOAD_ATTACHMENT (:morID, :attachmentType, :phpCur); END;"); 
if (!$stmt) { 
    die('creating statement failed'); 
} 

// and so on and on. Test the return values of each oci* function. 

oci_close($connection); 

header('Content-Disposition: attachment; filename='.$_GET['fileName']); // at least at basename() here 
header('Content-length: '.$_GET['fileSize']); // strange... 
header('Content-type: '.$_GET['mimeType']); // possible but still strange... 
echo $output; 
exit; 
+0

這當然讓我更靠近一步。隨着你的建議,我現在得到一個「OCI-Lob類的對象無法轉換爲字符串...」錯誤。尋找這個錯誤,看起來像我應該有 \t $ row = oci_fetch_array($ phpCur,OCI_ASSOC + OCI_RETURN_LOBS); 而不是 \t $ row = oci_fetch_array($ phpCur); 有了這個參數,我現在實際上下載了文件的字符表示,而不是打開或保存文件的提示。我現在如何克服這一點? – user39653 2010-08-10 16:46:07

+0

只要尚未向客戶端發送任何輸出,就可以在「任何位置」執行header()。你確定在header('Content-type ...')之前沒有輸出嗎?使用腳本示例中的error_reporting()/ ini_set()行,如果header()之前有輸出,則會看到「Warning:headers already sent」(警告:頭文件已發送) – VolkerK 2010-08-10 19:51:13

0

使用你的數據庫的查詢和excecute先在這裏是數據字段BLOB數據:

$sql="SELECT FILE_NAME,data,length(data) as filesize FROM branch_data where id='$id'"; 
$r = $db->execute($sql); 
$filename=$r->data[0]['FILE_NAME']; 
$d=$r->data[0]['DATA']; 
$filesize = $r->data[0]['FILESIZE']; 
header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="'.$filename.'"'); 
header('Cache-Control: must-revalidate'); 
header('Pragma: public'); 
header('Content-Length: ' .$filesize); 
echo $d->load();