I have to encrypt a file and save it in mysql as a blob, then decrypt it and make it available for download.
I save the file in a blob like so:
$certificate_tmp=$_FILES['certificate']['tmp_name'];
$certificate=openssl_encrypt(file_get_contents($certificate_tmp),$ciphers,$password_tmp);
$wpdb->insert("my_table",array("certificate"=>$certificate));
Note: I've cut unrelated code, the table is not just certificate, but I don't want this to get confusing.
This is the download php page:
$password_tmp=$_SESSION['pwd']; //decrypt password
global $wpdb; //wordpress db conncetion
$results_file = $wpdb->get_row("select * from my_table where id='$id'",ARRAY_A); //i get the id from wp's curr_user
$m_file = openssl_decrypt($results_file['certificate'],"AES-128-CBC",$password_tmp);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\certificate".$id."\"");
header('Content-Transfer-Encoding: binary');
print_r($m_file);
And everything works perfectly with text files, but the result is empty with binary files, although in the blob the binary file is there.
EDIT
My guess is, as soon as I decrypt the file from the db blob, php or html (because of print_r) understands that it is a binary file and doesn't let you show it because of security reasons. You can't execute programs on the web like .exe or .bin, although the files I upload, either binary or text have no extension.
From what I understand php treats binary files as strings, but file_get_contents is binary safe.
I think not using blobs would be the best approach for this, but I cannot do that, I have to use blobs.
EDIT 2
The problem seems to be openssl which doesn't seem to like binary data, I've tried the same code using mcrypt and it works perfectly.
Make sure you are decrypting the data using the same key.
Why do you use print instead of print_r?
Try to add the content length:
header('Content-Length: '.strlen(YourFileData));
For more information please visit:
http://www.media-division.com/the-right-way-to-handle-file-downloads-in-php/
Related
First of all, I apologize if the question is not clear, I'm explaining it below.
For every file uploaded, I'm renaming the file and recording the hash values (using sha1_files function, please suggest if there are some better or faster hashing techniques for the file in php) in a separate DB table and checking the hash of every new file to avoid duplicate files.
In this manner, the one uploading a duplicate file will get an error msg and the file won't be uploaded.
My question is, is there any techniques or algorithm by which I can prevent duplicate file upload but the duplicate file uploader will be unaware of it and will find the file in his/her account with a different name than the one already present. However, users won't be able to upload banned files by any means.
Yes, you should use xxhash which is much faster than sha1.
According to their benchmarks:
The benchmark uses SMHasher speed test, compiled with Visual 2010 on a
Windows Seven 32-bits box. The reference system uses a Core 2 Duo
#3GHz
SHA1-32 is 0.28 GB/s fast, and xxHash is 5.4 GB/s.
The PHP library is only getting a string as input, so you should use the binary library, and have something like this in your PHP:
list($hash) = explode(" ", shell_exec("/path/to/xxHash/xxhsum " . escapeshellarg($filePath)));
echo $hash;
Installing xxhash:
$ wget https://codeload.github.com/Cyan4973/xxHash/tar.gz/v0.6.3 -O xx.tar.gz
$ tar xvzf xx.tar.gz
$ cd xxHash-0.6.3; make
Just add some extra logic in your code possibly using an extra table or extra fields in the existing table (it is up to you, there is more than one way to do it) that saves the file to an alternate location should you discover it is a duplicate rather than sending an error. Not sure, though, if what you are doing is a good idea from the UI design point of view, as you are doing something different with the user input in a way that the user will notice without telling the user why.
Use an example like this to generate your sha1 hash client side before upload.
Save all your uploaded files with their hash as the filename, or have a database table which contains the hash and your local filename for each file, also save file size and content type.
Before upload submit hash from client side to your server and check for hash in database. If its not present then commence file upload. If present then fake the upload client side or whatever you want to do so the user thinks they have uploaded their file.
Create a column in your users table for files uploaded. Store a serialised associative array in this column with hash => users_file_name as key=>value pairs. Unserialize and display to each user to maintain their own file names then use readfile to serve them the file with the correct name, selecting it server side using the hash
As for your URL question. Create a page for the downloads but include the user in the url as well, so mysite.com/image.php?user=NewBee&image=filename.jpg
Query the database for files uploaded by NewBee and unserialize the array. Then:
$upload = $_GET['image'];
foreach($array as $hash => $filename){
if($filename == $upload)
$file = $hash;
}
Seach database for the path to your copy of that file, then using readfile you can output the same file with whatever namme you want.
header("Content-Description: File Transfer");
header("Content-type: {$contenttype}");
header("Content-Disposition: attachment; filename=\"{$filename}\"");
header("Content-Length: " . filesize($file));
header('Pragma: public');
header("Expires: 0");
readfile($file);
You could create an extra table which links files uploaded (so entries in your table with file hashes) with useraccounts. This table can contain an individual file name for every file belonging to a specific user (so the same file can have a different name per user). With current technologies you could also think about creating the file hash in the browser via javascript and then upload the file only if there isn't already a file with that hash in your database if it is you can instead just link this user to the file.
Addition because of comment:
If you want the same file to be accessible through multiple urls you can use something like apache's mod_ rewrite. I'm no expert with that but you can look here for a first idea. You could update the .htaccess dynamically with your upload script.
I am using PHP and MySQL for my programming.
I have stored some Base64 strings (which are encoded from files). I know that base64_decode(); can decode Base64 strings to files.
Now, I want to decode these Base64 strings to files, by PHP, without saving it in my web server; but, web browser can download it from web link (http://example.com/save.php?fileid=23413).
In my PHP page, http://example.com/save.php?fileid=23413, I did:
I can use echo(); for printing Base64 strings. So, there is no problem with my MySQL queries.
I have delete echo(); from my PHP page.
I tried to use base64_decode(); to decode Base64 strings to files. I want when I nagivate to this page, it will export a file. But, It returns an empty page.
Can you help me to decode Base64 strings to files, by PHP, without saving it in my web server, and web browser can download it from web link (http://example.com/save.php?fileid=23413)?
Try adding headers to the script before echoing the output
header('Content-Description: File Transfer');
header("Content-type: application/octet-stream");
header("Content-disposition: attachment; filename= ".$file."");
echo base64_decode($file);
I am currently working on a project that has files stored in a DB as blobs. I need to attach the file to an e-mail and send it out via PHPMailer. I am familiar with $mail->addAttachment(), however, this function seems to take in a file path only, which I don't have. I was wondering if there is any way to manipulate the blob and feed to this function ?
I appreciate any suggestions, thanks in advance!
The following successfully creates a 'Save As' dialog of the file I need to attach:
header("Content-disposition: attachment; filename={$filename}.{$file_ext}");
header("Content-type: application/octet-stream");
echo $pdf['data'];
exit;
The addStringAttachment method is capable of handling such case. According to its doc:
* Add a string or binary attachment (non-filesystem).
* This method can be used to attach ascii or binary data,
* such as a BLOB record from a database.
How do I generate a pdf-file from a binary file retrieved from database in php5? It comes base64 encoded, and I just decoded it, but don't know what to do next...
The binary data is simply the actual file, or rather the important contents of that file, just without file name.
$base64 = /* some base64 encoded data fetched from somewhere */;
$binary = base64_decode($base64);
And there you have the file data/contents of the file in the $binary variable. From here, it depends on what you want to do. You can write the data to a file, and you get an "actual" PDF file:
file_put_contents('my.pdf', $binary);
You can spit the data out to the browser with an appropriate header, and the user will receive something that looks like a PDF file to him:
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="my.pdf"');
echo $binary;
I'm repeating your last sentence .:) I dont know what is the question! :). If you want to pus the file to a browser, you can set the headers and stream the decoded content. Or if you want the file as is, write on to file system and use it. Please be more clear on your question!
Thanks!!
I am using PHP 5.3.5 and postgreSQL. I am storing and extracting images from database.
For storing i am doing this:
$escaped_data = base64_encode(file_get_contents($_FILES['fileUpload']['tmp_name']));
$fileModel->setBinary_Data($escaped_data);
It's working, i received the image in my database (Bytea field).
The problem is to extract this, i am trying this code to extract my images:
$file_info = $fileModel->getBinary_Data($id_file); // This function return the binary_data of the image
header('Content-Type: image/jpeg;base64');
header('Content-Disposition: attachment; filename=' . $file_info['_name']);
base64_decode($file_info['binary_data']));
When i download the image, i can't see the image...
With echo in:
echo base64_decode($file_info['binary_data']);
This happen:
http://imageshack.us/f/18/encodez.jpg/
After, i am trying using the function stream_get_contents inside base64_decode, but doens't work.
Someone know how i can download my images with php?
Thanks anyway...
Well obviously your custom getBinary_Data() returns $file_info['binary_data'] as a resource, not a string.. so either change the function or use base64_decode(file_get_contents($file_info['binary_data'])));
And try to use fclose($file_info['binary_data']); too then.
P.S. Wasn't there a blob type for binary data in postgre?