auto rename of file when its already exist.. PHP CODE - php

upload.php
<form enctype="multipart/form-data" action="uploader.php" method="POST">
Choose a file: <input name="uploadedfile" type="file" /><br />
Choose a file1: <input name="uploadedfile1" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
^Image of the upload.php^
uploader.php
<?php
mysql_select_db("test");
$target_path = "uploads/" . basename( $_FILES['uploadedfile']['name']);
$target_path1 = "upload1/" . basename( $_FILES['uploadedfile1']['name']);
$currentfile = $_FILES['uploadedfile']['name'];
$currentfile1 = $_FILES['uploadedfile1']['name'];
$dbfiles = mysql_query("SELECT * FROM new WHERE amount='$currentfile' || amount='$currentfile1'");
if(mysql_num_rows($dbfiles) > 0 )
{
}
else
{
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path))
{
echo "file1: ".$_FILES['uploadedfile']['name']."<br>";
$file1 = basename( $_FILES['uploadedfile']['name']);
mysql_query("insert into new (amount) values('$file1')");
}
if(move_uploaded_file($_FILES['uploadedfile1']['tmp_name'], $target_path1))
{
echo "file2: ".basename( $_FILES['uploadedfile1']['name']);
$file2 = basename( $_FILES['uploadedfile1']['name']);
mysql_query("insert into new (amount) values('$file2')");
}
}
?>
introduction and the problem
This code will allow the user to upload 2 files, then their respective file name will save to the new(name of table) , I need it to save in table so that i have history who was the uploader of the file and simply can retrieve it or download it. The first button is the uploadedfile where in the file will save in uploads folder, then the button below is the uploadedfile1 where in the file will save in upload1, when the user put 2 files in this 2 buttons, then the user click save, it will save to their prepared folder(uploads or upload1), when the user only attach one file whether in the button uploaderfile or uploaderfile1 and click Upload file/save/submit, it will still save its file name to table new and save the file in the following folder(uploads of upload1).
The Problem is when the user upload a same file name, For example abc.jpg is already exist in table new and in folder(uploads of upload1), but there some user also upload abc.jpg.. the problem is in the folder(uploads of upload1) the abc.jpg will only one(one pcs..) because same file name.. i think the solution is the rename, where in the abc.jpg that is currently uploaded will became abc_1.jpg, also in the table new abc_1.jpg will be save..

You shouldn't save the files by their original name.
It is better practise to assign the file a unique identifier in the database, and use this same identifier for the file name.
Then have a downloads page which retrieves the file path and original name from the database and send it to the user with readfile and set relevant headers:
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file_name).'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: '.filesize($file_path));
ob_clean();
flush();
readfile($file_path);
die();
This is also better from a security point of view as the users no longer need to know or have access to the file location on the server so if they upload anything malicious, they will be unable to call the file directly.
Edit:
To apply this, you will need to have a table for your file uploads with an autoincrementing ID field.
You can then insert the original filename and other relevant information into the database using mysql_query (as you are already using it in your example). You then need to pass the query into mysql_insert_id which will give you the unique identifier for the row you just inserted. Use this to name your file, followed by a '.dat' extension in your uploads folder.
When it comes to downloading, have a download page which takes an id by either query string or post parameter and then use this to look up the information in the database. You can figure out the filename given the ID as this is what you used to store it in the first place.
Once you have the file path and original name, you can use the code above to present the user with the download (after replacing $file_name and $file_location with your own parameters if you call them something else).
The downloads page will also need to handle any checks on whether or not the user is allowed to download the file.

Related

Initiate download without button

I'm a PHP newbie ... and stuck!
I would like to realize this HTML/PHP project in a single file (as opposed to using .html and .php files separately).
Basically, 3 steps are necessary.
upload a PDF file.
process the PDF file. Output is a .txt file.
offer the user the processed .txt file without the standard download button.
(1.) and (2.) is already properly implemented and works fine. (3.) is my problem/question. The internet offers several solutions, but all with download buttons which the user has to press to trigger download from server to local machine. I would like to write (in PHP only) code which offers the user a Save Dialog Box, which permits saving the .txt file locally. Is this possible without any HTML code, hence solely by PHP?
Below the real code heavily simplified to the necessary.
<form action = "" method = "POST" enctype = "multipart/form-data">
Select PDF file to be uploaded.
<input type = "file" name="pdffile" />
<input type = "submit" name = "submit" value = "upload roster" />
</form>
<?php
if(isset($_FILES['pdffile'])) {
$errors = array();
$file_name = $_FILES['pdffile']['name'];
$file_size = $_FILES['pdffile']['size'];
$file_tmp = $_FILES['pdffile']['tmp_name'];
...
move_uploaded_file($file_tmp, "/home/user/pdf2txt/uploads/" . $file_name);
$cmd = "../../pdf2txt/pdf2txt ../../pdf2txt/uploads/" . $file_name;
...
// the stdout of pdf2txt is stored in /tmp/pdffile.txt
// initiate download to user - THAT'S MY PROBLEM/QUESTION
...
?>
EDIT
Maybe I was too short. The project should be realized inside a WordPress page. I use a PHP plugin which permits PHP code injection. Now ... using the code of #mrid, I get ...
Warning: Cannot modify header information – headers already sent by (output started at /home/geohei/mysite/WP_TEST/wp-content/themes/blackoot-pro/header.php:12) in /home/geohei/mysite/WP_TEST/wp-content/plugins/insert-php/insert_php.php(48) : eval()’d code on line 81
insert-php.php is the WordPress PHP plugin.
blackroot is the theme.
I understand that headers were already previously sent by the theme and I am not allowed to change them.
What can be done in such a situation?
Here's an example of
header('Content-Disposition: attachment; filename=' . basename($filename) . '"');
header("Content-type: text/plain");
header('Content-Length: ' . filesize($filename));
readfile($filename);

Using input[type="file"] to prompt the user to save the file

I am trying to achieve two actions from an input file tag. I have the following input:
<input id='file-input' name='attach' type='file' style='margin-left:15px;'/>
This is found in messages.php. What I am trying to achieve are two things:
If the file uploaded is over 1mb in size (or is a file which is not an image), then produce a button which on click opens the save as menu, from where a user can select where they wish to download the data.
And secondly, as mentioned, if the file size is lower than 1mb, then simply display the data on the page (only works for image files).
I have other pages where I have used input type="file" to upload profile images, and have just displayed the image on the page. But I am unsure on how I can execute (1) - how I can open a menu from where the user can save the data?
Just serve the file with a Content-Disposition: attachment header, see PHP Outputting File Attachments with Headers
Among other nice answers I will do it this way.
I have made it possible by clicking on your suggested Download button, if file is greater than 1Mb you will get download pop up like this
Otherwise if file less than 1Mb it will just show it on browser will look like this:
Btw, the code is self explaining.
PHP part called index.php
<?php
$filename = "test3.jpg";
$maxSize = 1000000; // 1Mb
if (isset($_POST['save']))
fileHandler($filename, $maxSize);
function fileHandler($filename, $maxSize)
{
$fileinfo = getimagesize($filename);
$filesize = filesize($filename);
$fp = fopen($filename, "rb");
if ($fileinfo && $fp)
{
header("Content-Type: {$fileinfo['mime']}");
if ($filesize > $maxSize)
{
header('Content-Disposition: attachment; filename="NewName.jpg"');
}
fpassthru($fp);
exit;
} else
{
echo "Error! please contact administrator";
}
}
?>
HTML part inside index.php but it is important this code should comes after php tags and not before.
<form action="index.php" method="post">
<button type="submit" style="border: 0; background: transparent" name="save">
<img src="download.jpg" alt="submit" />
</button>
</form>
Note: it is important your php document start directly with <?php ..., please read
You won't need to fake a click or something. You probably need something like this.
User selects file and clicks the "Upload file" button.
File gets uploaded using e.g. PHP.
PHP displays the contents of the file, using the correct headers.
PHP determines if the file is smaller or larger than 1MB.
If the file is larger, set a header that forces the user to download the file (causing a select location popup).
If the file is smaller, do not set the header, causing the file to display in the browser.
Where Italic is a user action and Bold is a server action.
You can do this by getting the image mime type and setting the content disposition and content type headers:
$file = 'path/to/file';
if (file_exists($file)) {
$contents = file_get_contents($file);
$fileSize = filesize($file);
$image_info = getImageSize($file);
$mimeType = $image_info['mime'];
header("content-disposition: attachment; filename=" . basename($file));
header("content-type:$mimeType");
header("Content-length: $fileSize");
echo $contents;
exit;
}

Codeigniter rename downloaded file?

Let's say the user upload a zip file called codeigniter.zip. And my application saved it with name 1.zip that is the file's id in database table. Also it saved file's original name to the table. If the user download this file he download it by name 1.zip. How can i give this file to the user with name codeigniter.zip? Thank you.
You could do something like this:
$actual_filename = '1.zip'; // I assume this will come from some model's method
$desired_filename = 'codeigniter.zip' // same is assumed here
header('Content-Disposition: attachment; filename=' . $desired_filename);
echo file_get_contents('/path/to/' . $actual_filename);
Content-Disposition: attachment should make the browser prompt the user to download the file, and filename= tells the browser what to call the file [by default].

File downloaded from PHP script is different than file on server

I have a html file that allows a user to submit a file to post a file to my 'upload_file.php' PHP script.
index.html:
<html>
<body>
<form action="upload_file.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
upload_file.php referenced above takes in a file, does some work, and spits out a xlsx file (using PHPExcel). After creating the PHPExcel object, this is how I write it to the server and then force the user to download:
// Save Excel 2007 file
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
$fileBase = explode(".",$_FILES['file']['name']);
$outFilename = $fileBase[0] . date('His') . ".xlsx";
$objWriter->save($outFilename);
$url = "http://localhost/QWDATA/$outFilename";
//Initiate user download of file
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"$outFilename\"");
echo readfile($url);
When I do this, the download is initiated successfully... with one issue:
Opening the file that is downloaded results in an error in excel:
"We found a problem with some content in $filename. Do you want us to
try to recover as much as we can? If you trust the source of this
workbook, click Yes."
Clicking "yes" on the excel error results in a 'repaired' xlsx file opening and looking exactly as one would expect. Looking at a log of repairs that were done gives me this:
error129480_02.xmlErrors
were detected in file
'C:\XPATHX\$filename.xlsx'Excel
completed file level validation and repair. Some parts of this
workbook may have been repaired or
discarded.
... which is to say, nothing specific.
Tracking the issue back, opening the file directly from the server does NOT result in this error; telling me something additional is going on in the download code above.
My question is: What could be causing this and/or how can I solve the problem?
readfile echoes by itself. You don't need to call echo.
Actually, doing so, will echo the result of readfile (which is the size of the file as an integer), so that causes a couple of extra bytes at the end of the file. This will be easy for Excel to fix, and probably won't result in actual data loss, but still the file is invalid, so you get the error.
Looking at the file on the server and the file that downloads, I noticed a 5 byte difference.
Having already removed all other echo commands from the php file due to suggestions here (https://phpexcel.codeplex.com/discussions/42854) and here (PHPExcel File format or extension is not valid) I knew something had to be adding information.
I made the following changes to the above code -- taking out the escaped quotes in the filename (just a personal guess) in the header setting and changing echo to readfile (as suggested here: http://webdesign.about.com/od/php/ht/force_download.htm). Thus giving me:
// Save Excel 2007 file
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
$fileBase = explode(".",$_FILES['file']['name']);
$outFilename = $fileBase[0] . date('His') . ".xlsx";
$objWriter->save($outFilename);
$url = "http://localhost/QWDATA/$outFilename";
//Initiate user download of file
header("Content-disposition: attachment; filename=$outFilename");
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Transfer-Encoding: Binary");
readfile($outFilename);
This appears to directly download the file with no additions -- which means excel is happy and the problem is solved.
In short, it appears echo readfile($outFilename); needed to just be readfile($outFilename);

Rename uploaded files to avoid overwriting

I have this simple script which works fine, but currently overwrites files with duplicate names. How can I avoid this?
<?php
// Configuration - Your Options
$allowed_filetypes = array('.mp3'); // These will be the types of file that will pass the validation.
$max_filesize = 1048576; // Maximum filesize in BYTES (currently 0.5MB).
$upload_path = './uploads/'; // The place the files will be uploaded to (currently a 'files' directory).
$filename = $_FILES['userfile']['name']; // Get the name of the file (including file extension).
$ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Get the extension from the filename.
if(!in_array($ext,$allowed_filetypes))
header('Location: http://www.website.com/five/error');
if(filesize($_FILES['userfile']['tmp_name']) > $max_filesize)
header('Location: http://www.website.com/five/error');
if(!is_writable($upload_path))
header('Location: http://www.website.com/five/error');
if(move_uploaded_file($_FILES['userfile']['tmp_name'],$upload_path . $filename))
// echo 'Your file upload was successful, view the file here'; // It worked.
header('Location: http://www.website.com/five/sent');
else
header('Location: http://www.website.com/five/error');
?>
Add an if (file_exists($upload_path.$filename)) before you upload, and set $filename to something else if it does.
One option is to use a database to store the original names, along with a unique id.
Then you can save the file as whatever unique name you want.
Use just the id... file = 1
Use the id and extension = 1.mp3
Use a combination of the id and name = 1_name_of_file.mp3
Or any other unique naming option.
Then you use php to serve the files. Setting the header with the original file name.
Users would not be aware of how you are storing the file. Multiple files with the same name could be uploaded and downloaded with that name, but stored uniquely on the server.
<?php
$actualFile = './uploads/'.$id;
// Can use some smarts to determine the mime type here
header('Content-type: application/force-download');
// The user will be prompted to save it as the filename given here.
header('Content-Disposition: attachment; filename="'.$originalName.'"');
header("Content-Length: ".filesize($actualFile));
// The actual file on the server
readfile($actualFile);
?>
There are also a number of other header options you can set for caching and so on.
http://php.net/manual/en/function.header.php
Fileinfo is a good extension for determining mimetypes
http://www.php.net/manual/en/function.finfo-file.php
Use your own filename instead of the original.
This could for example be generated via uniqid()
store the file with a hash as the name, and store the original filename in a database/flat file along with the hash.
if you want to use flat files it could just be that the user file gets stored as .dat and the info about the file is stored as either .json or .xml or even just a serialized PHP object if you prefer.
also, your file-extension detecting logic fails as soon as the filename has more than one dot (period) in the name.

Categories