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.
Related
I need to print out all the files that I've saved in a database and then make it possible to download them. I am able to echo them, but I don't know how to make a download "button" to download them to the computer.
The datbase has two columns: ID and Ime.
I tried using a tag from HTML with no luck. I was able to echo buttons next to file names, but I couldn't download them (I tried using file_put_contents method)
This is the code that outputs file names (Ime = Name in my language).
<?php
$conn = mysqli_connect('localhost','root','usbw','down');
$query = "SELECT * FROM datoteka";
$result = mysqli_query($conn,$query);
$result_check = mysqli_num_rows($result);
if($result_check > 0){
while($row = mysqli_fetch_assoc($result)){
echo $row["Ime"]."<br>";
}
}
?>
The output looks like this:
datoteka2019-04-01-15-44.doc
datoteka2019-04-01-15-48.doc
datoteka2019-04-01-15-16.pdf
Files in database that I want to be able to download (3 for now, could be more)
There should be a download button (or something cliclkable) next to each file name on website that would enable me to download this file from the database (one file at time, not all at once).
I once made a similar script, what you have to do is set some headers and echo the data from database.
An example of that could be, assuming that the data is in $row['filedata'], the following
<?php
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=".$row['Ime']);
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
echo $row['filedata'];
?>
Now you have to know what file to download first, and for that we can use a GET or POST parameter
<?php
$fileID = htmlentities($_GET['fileID']);
$conn = mysqli_connect('localhost','root','usbw','down');
$fileID = mysqli_real_escape_string($conn, $fileID); // ALWAYS ESCAPE USER INPUT
$query = "SELECT * FROM datoteka where `ID`=$fileID";
$result = mysqli_query($conn, $query);
$result_check = mysqli_num_rows($result);
if($result_check > 1 || $result_check < 1){ //If more then 1 result die
die('inavlid ID');
}
$row = mysqli_fetch_assoc($result);
//and here the above mentioned lines
?>
The easiest way to add a download button to the page would be by using the window.open() function in JavaScript like so:
echo $row['Ime']."<button onclick='window.open(\"download.php?fileID=".$row['ID']."\");'>Download</button><br>";
This will open a new window which will download the file
The total would look something like this
For download.php:
<?php
$fileID = htmlentities($_GET['fileID']);
$conn = mysqli_connect('localhost','root','usbw','down');
$fileID = mysqli_real_escape_string($conn, $fileID); // ALWAYS ESCAPE USER INPUT
$query = "SELECT * FROM datoteka where `ID`=$fileID";
$result = mysqli_query($conn, $query);
$result_check = mysqli_num_rows($result);
if($result_check > 1 || $result_check < 1){ //If more then 1 result die
die('inavlid ID');
}
$row = mysqli_fetch_assoc($result);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=".$row['Ime']);
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
echo $row['filedata'];
?>
and for index.php
<?php
$conn = mysqli_connect('localhost','root','usbw','down');
$query = "SELECT * FROM datoteka";
$result = mysqli_query($conn,$query);
$result_check = mysqli_num_rows($result);
if($result_check > 0){
while($row = mysqli_fetch_assoc($result)){
echo $row['Ime']."<button onclick='window.open(\"download.php?fileID=".$row['ID']."\");'>Download</button><br>";
}
}
?>
You can read here https://www.php.net/file_put_contents,
and you need to know where the path file is. ex:
/users/john/downloads/namefile.doc
I'm trying to extract a BLOB from mysql and send it to the requester without saving it on the server. I've gotten it to work with PDF files, but some of our clients want xls files. When getting the xls file, the downloaded file is garbage. In HxD it looks like it is putting an extra 11 bytes on the front of the file.
Here is my code, both working and not working:
function blob_download_xls() {
$mysqli = openMySQLconnetion();
$sql = "SELECT * FROM Uploads;";
$results = $mysqli->query($sql);
$row = $results->fetch_assoc();
$bytes = $row['filedata'];
header('Content-type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="report.xls"');
print $bytes;
}
function blob_download_pdf() {
$mysqli = openMySQLconnetion();
$sql = "SELECT * FROM Uploads;";
$results = $mysqli->query($sql);
$row = $results->fetch_assoc();
$bytes = $row['filedata'];
header("Content-type: application/pdf");
header('Content-Disposition: inline; filename="report.pdf"');
print $bytes;
}
Any idea what I'm doing wrong?
I asked this question with a new account without realizing that I already had an account here. I've solved the problem and it was stupid.
When writing my function.php, I put a closing tag '?>' on the end of the file. After this tag was a 0d0a for a line feed return and then 9 20's for 9 spaces. I removed the closing tag and now it works perfectly.
The correct way to deal with this is to die() immediately after printing the bytes, before the server has a chance to output any HTML that may succeed the PHP code.
function blob_download_xls() {
$mysqli = openMySQLconnetion();
$sql = "SELECT * FROM Uploads;";
$results = $mysqli->query($sql);
$row = $results->fetch_assoc();
$bytes = $row['filedata'];
header('Content-type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="report.xls"');
print $bytes;
die();
}
I have the following script that will export data from my database using php to csv file. Everything works fine, except when I try to open the file in excel, I get "file is corrupt". When I run this code it shows the error - "The file is corrupted and can not be opened." Thanks in advance!
<?php
// Connection
include_once('conn.php');
$sql = "select * from info";
$qur = mysql_query($sql);
// Enable to download this file
$filename = "sampledata.csv";
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: text/csv");
$display = fopen("php://output", 'w');
$flag = false;
while($row = mysql_fetch_assoc($qur)) {
if(!$flag) {
// display field/column names as first row
fputcsv($display, array_keys($row), ",", '"');
$flag = true;
}
fputcsv($display, array_values($row), ",", '"');
}
fclose($display);
exit;
?>
I found the answer of my own question. Just need to add the ob_clean() line before we call the headers to download csv file to clear the output buffer. This will solve the error of not opening csv file in excel.
I am using microsoft tag php library by Scott Vanderbeck.
It has a function to output the barcode to browser as an image to browser, but I would like download and save to disk. My goal is to loop through all the tags and download each barcode as an image onto a disk. I am not sure how to accomplish this.
Here is my code
require_once('MSTag_v2.php');
$MSTagAuthToken = "your token";
//Create an MSTag interface instance
$msTag = new MSTag();
//Create User Credentials
$userCredential = new UserCredential($MSTagAuthToken);
//Display Microsoft Tag image in browser
$result = $msTag->GetBarcode($userCredential,'MAIN','Cyclamen coum Pewter','jpeg',1);
if($result)
{
ob_start();
$length = strlen($result);
header('Last-Modified: '.date('r'));
header('Accept-Ranges: bytes');
header('Content-Length: '.$length);
header('Content-Type: image/jpeg');
print($result);
ob_end_flush();
exit;
}
else
{
echo $msTag->getLastException();
}
You could save the images directly to disk
if($result)
{
file_put_contents($filename, $result);
}
Just generate a filename for each so you do not overwrite them (maybe use tempnam()).
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.