2010-08-10 58 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();