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.
Related
I have a database table which stores the document file name and on the local pc i have a folder named as uploads which stores the actual files the user uploads.
The way i upload files are as follows,
$filename = $_FILES['attachment']['name'];
// destination of the file on the server
$destination = 'uploads/' . $filename;
// get the file extension
$extension = pathinfo($filename, PATHINFO_EXTENSION);
// the physical file on a temporary uploads directory on the server
$file = $_FILES['attachment']['tmp_name'];
$size = $_FILES['attachment']['size'];
if (!in_array($extension, ['zip', 'pdf', 'docx'])) {
echo "You file extension must be .zip, .pdf or .docx";
} elseif ($_FILES['attachment']['size'] > 1000000) { // file shouldn't be larger than 1Megabyte
echo "File too large!";
} else {
// move the uploaded (temporary) file to the specified destination
if (move_uploaded_file($file, $destination)) {
$sender_name = $_POST['sender_name'];
$contact = $_POST['contactnumber'];
$sender_mail = $_POST['sender_email'];
$description = $_POST['description'];
$applied = date('Y-m-d');
$jobapply = "INSERT INTO `job_submission`(`NAME`, `CONTACT`, `EMAIL`, `MESSAGE`,
`APPLIED_ON`, `CAREER_ID`,`CV`) VALUES
('$sender_name','$contact','$sender_mail','$description','$applied','$idc','$filename')";
if (mysqli_query($connect, $jobapply)) {
echo "You Application Was Submitted Successfully! We Wish You All The Best";
}
} else {
echo "Failed to upload file.";
}
}
The results of this code is the file name along with the other data are stored in the database and on the other hand the file is also stored in the uploads directory.
Now i want to download the file stored in the folder to the machine by using a button. for which I have written a code as follows,
if (isset($_GET['file_id'])) {
$id = $_GET['file_id'];
// fetch file to download from database
$sql = "SELECT * FROM job_submission WHERE JOB_ID='$id'";
$result = mysqli_query($connect, $sql);
$file = mysqli_fetch_assoc($result);
$filepath = 'uploads/' . $file['CV'];
if (file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($filepath));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('uploads/' . $file['CV']));
readfile('uploads/' . $file['CV']);
exit;
}
}
The above code is called from a button inside a table,
<td>Download </td>
The file gets downloaded but it doesn't open and throws an error saying
Error Failed to load PDF document.
I have successfully uploaded pdf files to the database but now when I am trying to read the files I'm getting issue "Failed to load PDF" when I click on the link. I have checked my browser plugins there is no issue with it.
<?php
$con=mysqli_connect("localhost","root","");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
mysqli_select_db($con,"mahmood_faridi");
$query = "SELECT id, name FROM upload";
$result = mysqli_query($con,$query) or die('Error, query failed');
if(mysqli_num_rows($result)==0){
echo "Database is empty <br>";
}
else{
while(list($id, $name) = mysqli_fetch_array($result)){
echo "$name<br>";
}
}
if(isset($_GET['id'])){
$id = $_GET['id'];
$query = "SELECT content FROM upload WHERE id = '$id'";
$result = mysqli_query($con,$query) or die('Error, query failed');
$row = mysqli_fetch_row($result);
$content=$row['content'];
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $content . '"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
ob_clean();
ob_flush ();
#readfile($content);
}
mysqli_close($con);
?>
This is the “save file” code:
<?php
$con=mysqli_connect("localhost","root","");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if(isset($_POST['upload']) && $_FILES['userfile']['size'] > 0)
{
$fileName = $_FILES['userfile']['name'];
$tmpName = $_FILES['userfile']['tmp_name'];
$fileSize = $_FILES['userfile']['size'];
$fileType = $_FILES['userfile']['type'];
$fp = fopen($tmpName, 'r');
$content = fread($fp, filesize($tmpName));
$content = mysqli_real_escape_string($con,$content);
fclose($fp);
if(!get_magic_quotes_gpc())
{
$fileName = mysqli_real_escape_string($con,$fileName);
}
mysqli_select_db($con,"mahmood_faridi");
$query = "INSERT INTO upload (name, size, type, content ) ".
"VALUES ('$fileName', '$fileSize', '$fileType', '$content')";
mysqli_query($con,$query) or die('Error, query failed');
mysqli_close($con);
echo "<br>File $fileName uploaded<br>";
}
else
echo "File not uploaded"
?>
I was going to post this as a comment, but it got a bit too long.
When saving the file to the database, try base64_encoding the content, and then base64_decoding it when reading it out. PDFs look odd when viewed in text, and the collation of the database can affect the way it saves, or even what is saved. If one single character changes, you'll have a corrupt PDF.
Also make sure that error reporting is turned off, and that you have no spaces being output alongside the PDF which will also show as the file being corrupt.
I'd also consider splitting the functionality you have out into different files. It looks like everything is in one file there, which can lead to output happening when you don't fully expect it, again corrupting a download.
As an alternative, can you not save the PDF to disk and store the location in the database. You can then read the file as needed and output it, and then there's no issue of the PDF content being corrupted within the database. If you go down this route, make sure you give them unique names as two files could be uploaded with the same name and you might accidentally overwrite one.
Oooooops!
We all concentrated about encoding and database storing, but the problem is another!
When you output your PDF, you get the content from database, but you send this content to the user through:
#readfile($content);
readfile($content) outputs the contents of the file with filepath $content, but in $content there is not any filepath!
You simply change this line of code in
echo $content;
and your script will works.
(Read more about readfile)
I try to build an upload image system by using php.After testing it,the system echo out"Image is uploaded",but it doesn't shown in database.Here is my code here
upload.php
<?php
//connect database
include('config.php');
//file properties
if(isset($_FILES['image'])){
$file = $_FILES['image']['tmp_name'];
}
if(!isset($file)){
echo "Please select an image";
}
else{
$image = addslashes(file_get_contents($_FILES['image']['tmp_name']));
$image_name =addslashes($_FILES['image']['name']);
$image_size =getimagesize($_FILES['image']['tmp_name']);
if ($image_size == FALSE) {
echo "This is not an image";
}
else{
$insert = "INSERT INTO image(name,picture) VALUES ('$image_name','$image')";
if(!$insert){
echo "Problem uploading";
}
else {
$lastid =mysqli_insert_id($con);
echo "Image Uploaded <p />Your Image :<p /><img src=get.php?id=$lastid>";
}
}
}
?>
get.php
<?php
include ('config.php');
$id = addslashes($_REQUEST['id']);
$image = mysqli_query($con ,"SELECT * FROM image WHERE id=$id");
$image = mysqli_fetch_assoc($image);
$image = $image['picture'];
header("Content-type :image/jpeg");
?>
and I clicking the submit button without choosing any files this 2 line of warning is showing up
Warning: file_get_contents(): Filename cannot be empty in upload.php line 14.
line14 is this $image = addslashes(file_get_contents($_FILES['image']['tmp_name']));
Warning: getimagesize(): Filename cannot be empty in in upload.php line 16.
while line 16 is this $image = addslashes(file_get_contents($_FILES['image']['tmp_name']));
Any idea about this?
You need a function to send your query, otherwise you just filled up a string: this:
$insert = "INSERT INTO image(name,picture) VALUES ('$image_name','$image')";
should be followed by this:
mysqli_query($con, $insert);
The warnings are caused by multiple issues with your code. First you are checking whether the file has been uploaded in the wrong way: this
if(isset($_FILES['image'])){
$file = $_FILES['image']['tmp_name'];
}
Will always set a $file variable, even though no file has been selected into the form, leading therefore to never execute this if statement:
if(!isset($file)){
echo "Please select an image";
}
and to always execute what's in the else block instead, which causes the errors, because the functions you mentioned, which are contained in this else block, are not able to operate on any file.
Therefore simply checking the file upload correctly will solve the issue: one way to do this would be to first remove this, which is unuseful
if(isset($_FILES['image'])){
$file = $_FILES['image']['tmp_name'];
}
and then change this:
if(!isset($file)){
echo "Please select an image";
}
to this:
if(!isset($_FILES['image']['tmp_name'])){
echo "Please select an image";
}
After line 16 you need to echo the image data.
echo $image;
#ken, here is a function that I use to output the image by setting the correct headers:
function output_headers($filetype, $imgsize, $filename, $attachment=false)
{
header("Content-Type: {$filetype}");
header("Pragma: public");
header("Cache-Control: public");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 * 24 * 4 -1;
$ExpStr = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
header($ExpStr);
header("Cache-Control: max-age=$offset");
//header("Content-Type: application/octet-stream");
header('Accept-Ranges: bytes');
header("Content-Length: $imgsize");
#insert the filename we want into the image so it can be saved with something
# more meaningful that showimg.jpg. :-)
# 04/03/06
#attachment causes save as to appear, inline serves imbedded image.
if ($attachment)
header('Content-Disposition: attachment; filename="' . $filename . '"');
else
header('Content-Disposition: inline; filename="' . $filename . '"');
}
This is part of a php file called showimg.php.jpg
This needs to be saved into a separate directory with the following .htaccess file to get php to handle requests for .jpgs:
AddType application/x-httpd-php .jpg
In this way, the webpage refers to the image <img src='/img/showimg.php.jpg?<add your parameters here>
regards
Steve
I have created a upload form and a php file which extract the name, size, type of the file and stores it in a database upload script, in table files. The file is also given a uniqid which is also stored in the same table.
Now I am trying to build up a download.php file where I want that when a specific link with the uniqid in is opened the script look in databse for the file searching for the uniqid and show the information against it.?
Here is my upload.php
<?php
include('config.php');
function bytesToSize1024($bytes, $precision = 300) {
$unit = array('B','KB','MB');
return #round($bytes / pow(1024, ($i = floor(log($bytes, 1024)))), $precision).' '.$unit[$i];
}
$FileName = $_FILES['filename']['name'];
$FileType = $_FILES['filename']['type'];
$FileSize = bytesToSize1024($_FILES['filename']['size'], 1);
$Fileid = uniqid(rand());
$tmp_name = $_FILES["filename"]["tmp_name"];
if ($_FILES["filename"]["error"] > 0)
{
echo "Apologies, an error has occurred.";
echo "Error Code: " . $_FILES["fileToUpload"]["error"];
}
else
{
move_uploaded_file($_FILES["filename"]["tmp_name"],
"C:\wamp\www\upload\upload" . $_FILES["filename"]["name"]);
}
$query2 = "INSERT INTO files (id, name, size, type) VALUES ('$Fileid', '$FileName', '$FileSize', '$FileType')";
$result2 = mysql_query($query2);
echo <<<EOF
<p>Your file: {$FileName} has been successfully received.</p>
<p>Type: {$FileType}</p>
<p>Size: {$FileSize}</p>
<p>Temp Foler: {$tmp_name}</p>
<p>Download Link: localhost/upload/download.php?=$Fileid
EOF;
?>
Please first tell me which kind of link I should create like. localhost/download.php?=uniqid
will the above example work and how to make it work. I am confused?
Here I have tried to create a download.php file but it is not good
<?php
include('config.php');
$query = "SELECT * FROM files";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
?>
<?php
echo <<<EOF
File Name: <?php echo $row['name']; ?>
$row
EOF;
?>
This is the code you need. Consider storing byte count in the database for file size.
Of course it might need some changes to be exactly what you want.
<?php
include('config.php');
//get id from GET method and make sure that it's safe to be used in the query
$id=mysql_real_escape_string($_GET['id']);
$query = "SELECT * FROM `files` WHERE `id`='$id'";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
if (count($row)!=1) //check if our unique record has been found
die('Sorry but we could not find this file!');
$row=$row[0];
//send download headers
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$row['name']);
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Pragma: no-cache');
header('Content-Length: ' .$row['size']);
readfile(upload" . $row['name']); //I recommend you to change the path and file name of your uploaded files!
?>
Link example: http://yourdomain.com/download.php?id=123
I'm able to upload a file to mysql but when i download it, the content changes.. example i have test.txt with
"hello"
on it.. when i download it, the test.txt becomes
< pre class='xdebug-var-dump' dir='ltr'>string 'sfasfsafasfsaf' (length=14)
sfasfsafasfsaf
not sure, what's wrong..
this is my code for downloading the file:
<?php include("class_lib.php");
$db = new database();
$db->connect();
if(isset($_GET["file_id"])){
$file_id = $_GET["file_id"];
$query = "SELECT filename, filetype, filesize, bin_data " .
"FROM file_tbl WHERE id = '$file_id'";
$result = mysql_query($query) or die('Error, query failed' . mysql_error());
list($filename, $filetype, $filesize, $bin_data) = mysql_fetch_array($result);
var_dump($bin_data);
header("Content-length: $filesize");
header("Content-type: $filetype");
header("Content-Disposition: attachment; filename=$filename");
echo $bin_data;
}
?>
for images also, it downloads but there's no image anymore.. it only shows "no preview available".. is this with my download script above?
or maybe this upload script i have:
$fileid = (string) ($lastemp_id + 1);
$fileName = basename($_FILES['binFile']['name']);
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
$fileName .= "_fileid_" . $fileid;
$fileName = $fileName.".".$extension;
$tmpName = $_FILES['binFile']['tmp_name'];
$fileSize = $_FILES['binFile']['size'];
$fileType = $_FILES['binFile']['type'];
$fileDesc = $_POST["txtDescription"];
$fp = fopen($tmpName, 'r');
$content = fread($fp, filesize($tmpName));
$content = addslashes($content);
fclose($fp);
if(!get_magic_quotes_gpc()){ $fileName = addslashes($fileName); }
if (isset($fileName)) {
$sql = "INSERT INTO file_tbl ";
$sql .= "(file_desc, bin_data, filename, filesize, filetype) ";
$sql .= "VALUES ('$fileDesc', '$content', ";
$sql .= "'$fileName', '$fileSize', '$fileType')";
mysql_query($sql, $db->connection) or die('Error: query failed' . mysql_error());
$message = "File uploaded.<br>"; var_dump($content);
}
else $message = "No file uploaded. (opt)";
what is wrong here exactly??
You're recklessly jamming binary data into your database without even a whiff of proper SQL escaping. What did you expect to happen? This short sample of code is so full of severe SQL injection bugs I hope for your sake it isn't deployed on the public internet.
For your own safety you should immediately stop using the creaky, old, deprecated mysql_query interface and spend the small amount of time necessary to switch your queries to PDO.
You would not have problems like this if you were using placeholders.
What you're seeing is probably the result of your spurious var_dump statement before you output your proper content.
Please try this, if upload file is flawless.
You can encode your binary data to 64 format when insert into database and also decode before download it.
<?php
ob_start();
include("class_lib.php");
$db = new database();
$db->connect();
if(isset($_GET["file_id"])){
$file_id = $_GET["file_id"];
$query = "SELECT filename, filetype, filesize, bin_data " .
"FROM file_tbl WHERE id = '$file_id'";
$result = mysql_query($query) or die('Error, query failed' . mysql_error());
list($filename, $filetype, $filesize, $bin_data) = mysql_fetch_array($result);
var_dump($bin_data);
ob_end_clean();
header("Content-length: $filesize");
header("Content-type: $filetype");
header("Content-Disposition: attachment; filename=$filename");
echo $bin_data;
exit;
}
?>