0

Using PHP, I'm trying to download a blob file that has already been uploaded to an Oracle 10g database. I've seen and imitated numerous examples I've found. When I access the page a File Download dialog appears allowing me to Open or Save. If I click Open, media player comes up as it should but never retrieves the file. If I choose Save, I always get an error message stating "Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found. Please try again later."

Below is my code which is pretty straight forward and pretty much like the examples I've found.

<?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;

?>
hakre
  • 193,403
  • 52
  • 435
  • 836
user39653
  • 1,275
  • 3
  • 15
  • 17
  • 1
    `header('Content-length: '.$_GET['fileSize']);` - The content lenght is determined by a GET parameter not the actual (byte) size of the blob data? Doesn't sound right. – VolkerK Aug 10 '10 at 16:03
  • The size of the attachment is stored in a separate field when the file is uploaded. I get that information using an AJAX call just before I call this page. I don't know if that's standard practice or not but as I understand it, I need to know the file size ahead of time in order to supply it for the header statement. Although, now that I see I've got my three header statements after my procedure call, I get I can get that information at the same time I download the blob. – user39653 Aug 10 '10 at 16:55

2 Answers2

1

Use your db query and excecute first here is the data field is blob data:

$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();
Pawel Maga
  • 5,428
  • 3
  • 38
  • 62
0

Add more error handling to your script. Any of the oci* function can fail and then subsequent steps will also fail. The documentation tells you what happens if a function fails and what the return value will be. E.g.

Return Values
Returns a connection identifier or FALSE on error.

If you set the Content-type header as late as possible, i.e. directly before the first output, you can send plain text or html that contains some sort of error message instead.

<?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;
VolkerK
  • 95,432
  • 20
  • 163
  • 226
  • That certainly gets me one step closer. With your suggestion I now get a "Object of class OCI-Lob could not be converted to string in ..." error. Searching for that error it looks like I should have $row = oci_fetch_array($phpCur, OCI_ASSOC+OCI_RETURN_LOBS); instead of $row = oci_fetch_array($phpCur); With that parameter in place I now actually download a character representation of the file instead of the prompt to open or save the file. How do I now get past this point? – user39653 Aug 10 '10 at 16:46
  • You can execute header() "anywhere" as long as no output has been sent to the client yet. Are you sure there was no output before header('Content-type...') ? With the error_reporting()/ini_set() line from my script example you'll get a "Warning: headers already sent" if there was output prior to header() – VolkerK Aug 10 '10 at 19:51