I have a simple html form, that saves the email message and multiple attachments path. I am saving the files on the server and their path to the database filed.
Now how can i retrive the files from its path, and then show them to user, when click on Download, I am using the following code for getting the file, but this is not working
$query = "
SELECT `type`, `name`, `size`, `file1`,`file2`,`file3`,`file4`,`file5`
FROM `upload` WHERE `id` = {$id}";
$result = $dbLink->query($query);
if($result) {
if($result->num_rows == 1) {
$row = mysqli_fetch_assoc($result);
header("Content-Type: ". $row['type']);
header("Content-Length: ". $row['size']);
header("Content-Disposition: attachment; filename=". $row['name']);
$path = $row['file1'];
$dir = opendir($path);
echo $dir;
while ($dir && ($file = readdir($dir)) !== false) {
echo $file;
}
The echoed file doesnot contain any data.
This i am doing now for only one file, whose path is at "file1". Similarly i have 5 attachments path, and i have to retrive them all in this code.
Please how can i do it.
First: You can't have more than one download like this. You can only send that header once and that's it.
Is $path the full path to the file? You could try is_readable($file) to check first in a test. Once you have the full path though, it's simple.
header("Content-Type: application/octet-stream");
header("Content-Length: ". $row['size']);
header("Content-Disposition: attachment; filename=". $row['name']);
readfile($row['file1']);
exit();
Readfile outputs directly and streams it, so you don't have to read the content in and then output it. Add the exit to make sure no other output get's added after it, or you could corrupt the file.
This works, assuming $row['file1'] has a correct path!
For multiple files, you have to make multiple calls. Like give the user mutliple links they can click on for downloads.
The only alternative is that you pack it together using zip for example, and send it as one large zipfile.
Related
I am trying to make a pdf-library where users can fill in which pdf-files they want to download and then the PHP file will get the filename from a database and make a path to the file and then it should download all selected files. But only get the last file downloaded.
This is my code for the download/output from the database:
Grateful for answer
$sql = "SELECT * FROM pdf WHERE id='$check'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$path = $row["path"];
$filename = $row["name"];
$file = $path."/".$filename;
header("Content-disposition: attachment; filename=".$filename);
header("Content-type: application/pdf");
readfile($file);
}
} else {
echo "0 results";
}
You can't send multiple files in a single response and you can't give multiple responses to a single request.
You might build an array of files to be downloaded and instruct the client (probably javascript in the browser) to request the files. Or you could zip them in a single ball and respond with that.
I am trying to download files from server and it works fine for pdf files, I am wondering is there a way to download any type of files such as doc, zip,.. etc.
My code:
<?php
$doc = $sqlite->readDoc($documentId);
if ($doc != null) {
header("Content-Type:" . $doc['mime_type']);
header('Content-disposition: attachment; filename="something"');
print $doc['doc'];
} else {
echo 'Error occured while downloading the file';
}
?>
You'll want to identify the file - maybe using this function:
http://php.net/manual/en/function.mime-content-type.php
and then you can create a switch to indicate the content-type and appropriate disposition. There's a decent example here: PHP - send file to user
A simple function that can be used to download any file formate form path.
function DownloadFile($strFilePath)
{
$strContents = file_get_contents(realpath($strFilePath));
if (strpos($strFilePath,"\\") > -1 )
$strFileName = substr($strFilePath,strrpos($strFilePath,"\\")+1);
else
$strFileName = substr($strFilePath,strrpos($strFilePath,"/")+1);
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=\"${strFileName}\"");
echo $strContents;
}
Usage Example
$file = $_GET['file_id'];
$path = "../uploads/".$file; // change the path to fit your websites document structure
DownloadFile($path);
I have a database that is storing all my pdf files for a website. The table has columns for the library_item_id, filename(name of the file), mime_type, File size, file_item(the Blob) and I have a php file called download.php. This file is supposed to download the correct file from the database when they user clicks the link. But when the file is downloaded and clicked to open I get Adobe saying it cannot open the pdf. Saying its not decoded correctly. Here is my download.php file:
require_once("scripts/connection.php");
if(isset($_GET["id"])){
$fid = $_GET["id"];
}
else{
header("Location: literature.php");
}
$sql= "SELECT filename, mime_type, file_item FROM library_items WHERE library_item_id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('s', $fid);
$stmt->execute();
$stmt->bind_result($filename, $mime, $file_item);
while($stmt->fetch()){
$file_name = $filename;
$mime_type = $mime;
$file = $file_item;
}
header("Content-length: ".strlen($file));
header("Content-type: $mime_type");
header("Content-disposition: download; filename=$file_name");
echo $file;
mysqli_close($conn);
I have tried everything I could think of including add the obj_flush() commands and all that it still gives me the same error. What am I doing wrong on this?
Here is the edit for the code inserting the file into the database.
session_start();
$display = trim($_POST["file-display-name"]);
$company = trim($_POST["companies"]);
$lib_cat = trim($_POST["library-cats"]);
if(empty($display) || empty($company) || empty($lib_cat)){
$_SESSION["errormsg"] = "Required information is missing please fill out all required fields.";
header("Location: ../library.php");
}
else{
$file_name = $_FILES['library-file']['name'];
$tmp_name = $_FILES['library-file']['tmp_name'];
$file_size = $_FILES['library-file']['size'];
$file_type = $_FILES['library-file']['type'];
$fp = fopen($tmp_name, 'r');
$content = fread($fp, filesize($tmp_name));
$content = addslashes($content);
fclose($fp);
if(!get_magic_quotes_gpc()){
$file_name = addslashes($file_name);
}
if(empty($content)){
$_SESSION["errormsg"] = "Required information is missing please fill out all required fields.";
header("Location: ../library.php");
}
else{
require_once("connection.php");
// Insert the logo into the companies photo table
$sql = "INSERT INTO library_items(filename, mime_type, file_size, file_item, display_name, company_id, library_category_id) VALUES(?,?,?,?,?,?,?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param('sssssss', $file_name, $file_type, $file_size, $content, $display, $company, $lib_cat);
if(!$stmt->execute()){
$_SESSION["errormsg"] = "Failed to add library item: ".mysqli_error();
header("Location: ../library.php");
}
}
unset($_SESSION["errormsg"]);
$_SESSION["successmsg"] = "Library Item successfully added into the database.";
header("Location: ../library.php");
}
UPDATE:
I now have the file downloading and attempting to display once the downloaded file is double clicked to open. It is telling me there is an invalid colorSpace. From what I can tell this is a problem when the file is uploaded into the database. From my upload file posted is there anything I am not doing correctly?
You need following changes. In the insert file
Instead of
$content = addslashes($content);
use
$content = base64_encode($content);
So while downloading, decode it.
$file = base64_decode($file_item);
Replace the following code
header("Content-type: '".$mime_type."'");
header("Content-Disposition: inline; filename='".$file_name."'");
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
readfile($file);
with
header("Content-length: ".strlen($file));
header("Content-type: $mime_type");
header("Content-disposition: download; filename=$file_name");
echo $file;
check if size of downloaded file is correct (matches size of file in database). If it is, you should be debugging the part where the file is inserted into database. If not - check if anything gets printed out before sending file to browser - maybe scripts/connection.php prints something like empty line, error message or BOM?
If you can't find it, try turning output buffering on and call ob_clean() before sending file.
Sorry for my english, I hope it's understandable.
I'm having a problem with PHP and my SQL Server.
When I try to save a file into the database as a varbinary(MAX) type, it works perfectly, but when I try to save a file of 180k or more in the result, I only get part of the image:
$handle = #fopen($fileTmpName, 'rb');
if ($handle)
{
$content = #fread($handle, filesize($fileTmpName));
$content = bin2hex($content);
#fclose($handle);
}
$select = mssql_query("EXEC [DB_Name].[dbo].[Table_Name] #Data = ".$content."");
$result = mssql_fetch_array($select);
$_SESSION['fileContent'] = $result['Data'];
<img src="../applications/framework/images.php" />
image.php file contains the following:
header("Content-type: ".$fileType);
header("Content-Length: ".$fileSize);
header("Content-Disposition: inline; filename=".$fileName);
echo $_SESSION['fileContent'];
As a result, I only get part of the image.
I mean that it only loads the first part of the real image. It seems that it inserts only the first part of the content into the database instead of all of it.
How can this be solved?
check the table structure. It might be the column might not be set up as a var(max)
We are in the midst of a data migration , and the project needs from one particular table BLOB data saved to files, and sent to the vendor, due to their structure
I am able to achieve this one at a time, but needed to create a batch process, as there are 50,000 rows/potential files.
my current code is
$sql = "SELECT a.guid AS file_name, a.attachment AS file_blob"
." FROM attachment a";
$squery = oci_parse($link, $sql);
oci_execute($squery);
while ($row = oci_fetch_array($squery, OCI_ASSOC | OCI_RETURN_LOBS)) {
header('Content-type: octet-stream;');
header('Content-disposition: attachment;filename='.$row['FILE_NAME']);
print $row['FILE_BLOB'];
}
oci_free_statement($squery);
I do understand that I would rather be saving the data rather than streaming it to the browser, I just am not wrapping my head around how to achieve this, should i be looking at php file I/O fputs()?
End result is I would like the process to batch write binary files based on the query to a folder
EDIT
Thank you for your direction and help, based on that I ended up coming up with two separate ways to achieve this
first i did the following getcwd() to verify where the server was pointing to, and did an absolute path if needed
$basedir = '/path/to/host/www/blobdoc/';
set permissions on the blobdoc folder then used either of the following scripts in the while loop
$filename='';
$filename=$basedir.$row['FILE_NAME'];
file_put_contents( $filename, $row['FILE_BLOB']);
$filename='';
$filename=$basedir.$row['FILE_NAME'];
$File = #fopen( $filename, 'w' );
if( $File ) {
if( FALSE === fwrite( $File, $row['FILE_BLOB'] ))
return FALSE;
fclose( $File );
return TRUE;
}
Instead of:
print $row['FILE_BLOB'];
Use something like:
file_put_contents( $filename, $row['FILE_BLOB']); //save locally
You need to write the blob to a file.
If you want to force a download of that file then you need to make use of the correct headers in combinarion with readfile, like so:
$file = '/var/www/html/file-to-download.zip';
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Length: ' . filesize($filename));
header('Content-Disposition: attachment; filename=' . basename($file));
readfile($file);