My php script has to handle with non-slug filename uploads, when for example, a user tries to upload a file "Имя на русском.jpg". Some methods don't handle it correct, so i use:
$overwrite = true;
$slug = true;
\Web::instance()->receive(NULL,$overwrite,$slug);
So, I get the "imja-na-russkom.jpg" file on server. The problem is that I need to catch this filename for DB, for which I tried this:
$filename = \Web::instance()->Slug($_FILES['userfile']['name'];
Which returns "imja-na-russkom-jpg" - not the name used in filesystem (not dot, but dash before extension).
So, my question is: Is there a way to catch the name, used in Web::receive() or, if not, is there a workaround to get it by means of F3? Thank you.
Ok, with ikkez' tip i figured that out:
$a = Web::instance()->receive(NULL,true,true);
$name = array_keys($a);
$name = pathinfo($name['0'], PATHINFO_BASENAME);
Here we upload file on the server and save it's name into $name variable. You can skip the last line and use
$name = $name['0'];
if you want to save the full path to your uploaded file.
the \Web::instance()->receive function returns an array of files that where uploaded. you'll see the slugged name in the array keys. check the example at http://fatfreeframework.com/web#receive
Related
I have a function like this:
fitImageSizeAndSave($_FILES["imageToUpload"]["tmp_name"], $target_file) { ... }
That function works well. The first argument is $_FILES["imageToUpload"]["tmp_name"]. Ok, it's good when an user upload an image from his local computer. But sometimes he enters a external link and I get that image like this:
$image = file_get_contents($_POST['external_link']);
How can I make $image like $_FILES["imageToUpload"]["tmp_name"] for passing it to the function?
use file_put_contents() and then reference the temporary file that you've just put the data into
#Martin Sounds a great idea, may you please add an answer? –
$_FILES["imageToUpload"]["tmp_name"] is simply a string to a file location on the server, it is not a resuorce in itself.
$filePathLocation = $_SERVER['DOCUMENT_ROOT']."/some-temporary/file/storage";
$imageData = file_get_contents($_POST['external_link']);
if($imageData){
file_put_contents($imageData, $filepathLocation);
}
else {
$filepathLocation = $_FILES["imageToUpload"]["tmp_name"];
}
fitImageSizeAndSave($filepathLocation, $target_file) { ... }
The above, step by step:
Set a temporary storage location; possibly based on microtime() or something unique (database Id, if relevant) to limit different processes overwriting the same file path.
get the contents of the $_POST file URL. save to a string variable.
Check if variable is loaded ok; else use uploaded temporary file location THIS IS FOR ILLUSTRATION ONLY - You should have a more complete process for checking which data to use and the validity of said data already set up in your script.
Send this variable to your custom function, knowning it is populated with one or the other of the possibilities above.
The below is the PHP script to get image from url and save into your location machine or into own server
$imageurl ='http://i.ndtvimg.com/i/2015-08/mahesh-babu_630x450_81440064359.jpg';
$content = file_get_contents($imageurl);
if(file_put_contents('imagefolder/randomImageName.jpg', $content)){
echo "File uploaded through URL";
}else{
echo "File not uploaded...";
}
Ok here is my code for uploading files
$ext_whitelist = array('pdf','doc','doc','mkv','mp4','mpg','mpeg','avi','flv','wma','ogg');
if(in_array($ext, $ext_whitelist))
{
$uniqid_file = uniqid('', true)."_".$file['name'];
$lokacija = $folder . "/" . $uniqid_file;
$encoded_uniqid_file = base64_encode($uniqid_file);
move_uploaded_file($file['tmp_name'], $lokacija);
$base_url= base_url("forms/fdownload/$encoded_uniqid_file/$path");
$form_data[$key] = "$uniqid_file ";
}
This checks file extension, so easy some could rename file, can someone help me to check file type proper?
Insted of a comment, I'll write a bit more as an answer.
Mimetype checking is a good thing if you want to know the type of the file, but it's not secure if you want to allow/deny the files at upload, because it's very easy to fake the mimetype.
Just try it, you can change it with a proxy or you can create a simple image, then add some php code at the end and rename it to .php. If you only check the mimetype, you can upload this .php file and run it on the server.
If you upload .jpg with php code in it, it's okay, the server won't push it through the php parser. (Except when you change the default configuration. (Apache: AddType, nginx: AddHandler )
There are some "secure" ways to check the uploaded files:
1. Check the extension and compare it to a whitelist.
This is the example in the question, but I'd like to write a complete solution. (A common mistake to check only the first think after the ., because there could be file names like: something.txt.php so always check the last postfix.)
$ext = array_pop(explode(".", $fileName));
$whitelist = array('pdf','doc','doc','mkv','mp4','mpg','mpeg','avi','flv','wma','ogg');
if (in_array($ext, $whitelist) {
//OK the extension is good, handle the upload.
} else {
//Wrong type, add error message.
}
If you use something like this, be careful and never allow extensions like .php and anything wich is in the server config.
2. Rename the file and drop the extension.
This is an another good way, but maybe you want to keep the original file name, the extension and the mimetype. You can store them in a database!
For this solution just take the original filename, add some random data (because if you upload into a single folder and you trie to upload something.jpg 2 time that would be a bad idea), then store this.
For example:
$newName = sha1($fileName.time());
move_uploaded_file($file['tmp_name'], $uploadPath . $newName);
Because the file doesn't have an extension, the server wont try to run it. (But if it's for example an image it'll work in the browsers, because they use the mimetype to determine the type and we didn't changed that.)
You can use
perl-file-mimeinfo
Ex:-
$file_path = '/tmp/temp.jpg';
$mimetype = trim(shell_exec("/usr/bin/mimetype -bi ".escapeshellarg($file_path)));
$info = null;
if(strpos($mimetype, "video/")===0 || strpos($mimetype, 'x-flash-video') > 0){
$info = 'video';
}elseif(strpos($mimetype, "audio/")===0){
$info = 'audio';
}elseif(strpos($mimetype, "image/")===0){
$info = 'image';
}
When someone uploads an image to my server, it uploads as the name they have for the image on their computer. I want the image name to become a short number as the name instead of the name, because when someone uploads an image as the same name, it overwrites it.
Here is my script where the names are defined:
if(isset($_FILES['fileup']) && strlen($_FILES['fileup']['name']) > 1) {
$uploadpath = $uploadpath . basename( $_FILES['fileup']['name']);
$sepext = explode('.', strtolower($_FILES['fileup']['name']));
$type = end($sepext);
list($width, $height) = getimagesize($_FILES['fileup']['tmp_name']);
$err = '';
This is a piece of (working) code I wrote a few years ago, that I still use to this day.
You probably may have to modify it to fit your script as well as the position in the script and the path.
However, I did replace my own original name (photo) with your fileup name.
Plus there are a few other goodies in there you probably could use, somewhere down the line.
$file_name = $HTTP_POST_FILES['fileup']['name'][0];
// should there be spaces in the uploaded file, replace them with an underscore
$file_name = str_replace(" ","_",$file_name);
$random_digit = substr(number_format(time() * rand(),0,'',''),0,10);
$new_file_name=$random_digit._.$file_name;
$path1= "./uploads/".$new_file_name;
// you can also use (my original write):
// copy($HTTP_POST_FILES['fileup']['tmp_name'][0], $path1);
move_uploaded_file($HTTP_POST_FILES['fileup']['tmp_name'][0], $path1);
$path_to_file_web = "http://www.example.com/uploads/$new_file_name";
The original script that I wrote was used on an older server with an older PHP version.
However, copy() will still work.
I do something like this:
i am just add some random string at beginning of file name
$new=generate_name(10);
$name=$new.$name;
Function generate_name();
function generate_name($long){
$cadena="[^A-Z0-9]";
return substr(eregi_replace($cadena, "", md5(rand())) .
eregi_replace($cadena, "", md5(rand())) .
eregi_replace($cadena, "", md5(rand())),
0, $long);
}
and generate this name:
03f396a35902-06-2013.csv
from 02-06-2013.csv file.
Not only do you not have to use the name provided when uploading a file, you shouldn't do so - like any user input, it is untrusted and could be used as a security hole.
So all you need to do is generate a random image name, and ensure it is not one that you've already used (e.g. by checking with file_exists() and using a do ... while loop to keep generating random names until that returns false). Then use that as the argument to move_uploaded_file(), which is the correct function to use for putting the file into a final location.
If you don't mind too much about the length and format, uniqid() is a good way to generate your filenames, because it is based on the current time so is unlikely to produce collisions.
I have searched far and wide on this one, but haven't really found a solution.
Got a client that wants music on their site (yea yea, I know..). The flash player grabs the single file called song.mp3 and plays it.
Well, I am trying to get functionality as to be able to have the client upload their own new song if they ever want to change it.
So basically, the script needs to allow them to upload the file, THEN overwrite the old file with the new one. Basically, making sure the filename of song.mp3 stays intact.
I am thinking I will need to use PHP to
1) upload the file
2) delete the original song.mp3
3) rename the new file upload to song.mp3
Does that seem right? Or is there a simpler way of doing this? Thanks in advance!
EDIT: I impimented UPLOADIFY and am able to use
'onAllComplete' : function(event,data) {
alert(data.filesUploaded + ' files uploaded successfully!');
}
I am just not sure how to point THAT to a PHP file....
'onAllComplete' : function() {
'aphpfile.php'
}
???? lol
a standard form will suffice for the upload just remember to include the mime in the form. then you can use $_FILES[''] to reference the file.
then you can check for the filename provided and see if it exists in the file system using file_exists() check for the file name OR if you don't need to keep the old file, you can use perform the file move and overwrite the old one with the new from the temporary directory
<?PHP
// this assumes that the upload form calls the form file field "myupload"
$name = $_FILES['myupload']['name'];
$type = $_FILES['myupload']['type'];
$size = $_FILES['myupload']['size'];
$tmp = $_FILES['myupload']['tmp_name'];
$error = $_FILES['myupload']['error'];
$savepath = '/yourserverpath/';
$filelocation = $svaepath.$name.".".$type;
// This won't upload if there was an error or if the file exists, hence the check
if (!file_exists($filelocation) && $error == 0) {
// echo "The file $filename exists";
// This will overwrite even if the file exists
move_uploaded_file($tmp, $filelocation);
}
// OR just leave out the "file_exists()" and check for the error,
// an if statement either way
?>
try this piece of code for upload and replace file
if(file_exists($newfilename)){
unlink($newfilename);
}
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $newfilename);
I've made an image upload script using the move_uploaded_file function. This function seems to overwrite any preexisting file with the new one. So, I need to check if the target location already has a file. If it does then I need to append something to the filename(before the extension so that the file name is still valid) so the filename is unique. I'd like to have the change be minimal instead of something like appending the datetime, if possible.
How can I do this with PHP?
When uploading files I will nearly always rename them. Typically there will be some kind of database record for that file. I use the ID of that to guarantee uniqueness of the file. Sometimes I'll even store what the client's original filename was in the database too but I'll never keep it or the temporary name because there is no guarantee that information is good, that your OS will support it or that it's unique (which is your issue).
So just rename it to some scheme of your own devising. That's my advice.
If you don't have any database reference, then you could use file_exists() for this but there's no guarantee that between the time of checking if something exists and moving it that something else won't use that same filename that you'll then overwrite. This is a classic race condition.
http://us3.php.net/manual/en/function.file-exists.php
Don't use file_exists() for the reason that it returns true (on *nix systems at least, since directories are specialized files) if the value is a directory. Use is_file() instead.
For example, say something fails and you have a string like:
$path = "/path/to/file/" . $file; // Assuming $file is an empty value, if something failed for example
if ( true === file_exists($path) ) { echo "This returns true"; }
if ( true === is_file($path) ) { echo "You will not read this"; }
It's caused a few problems in the past for me, so I always use is_file() rather than file_exists().
I use date and time functions to generate a random file name based on the time of upload.
Let's assume you are submitting a file from a form where you have an input named incomingfile like this:
<input type="file" id="incomingfile" name="incomingfile" />
First of all I use to "depure" the filename and copy it from the default temporary directory to a temporary directory. This is necessary to deal with special characters. I had troubles when I didn't adopt this practice.
$new_depured_filename = strtolower(preg_replace('/[^a-zA-Z0-9_ -.]/s', '_', $_FILES["incomingfile"]["name"]));
copy($_FILES["incomingfile"]["tmp_name"], 'my_temp_directory/'.$new_depured_filename);
With the following piece of code I check if the file exists, if so, I find a new name and finally copy it. For example if I want to write a file called myimage.jpg and it already exists I rename the pending file to myimage__000.jpg. If this exists as well I rename the pending file to myimage__001.jpg and so on until I find a non-existing filename.
$i=0; // A counter for the tail to append to the filename
$new_filename = $new_depured_filename;
$new_filepath='myfiles/music/'.$new_filename;
while(file_exists($new_filepath)) {
$tail = str_pad((string) $i, 3, "0", STR_PAD_LEFT); // Converts the integer in $i to a string of 3 characters with left zero fill.
$fileinfos = pathinfo($new_filepath); // Gathers some infos about the file
if($i>0) { // If we aren't at the first while cycle (where you have the filename without any added strings) then delete the tail (like "__000") from the filename to add another one later (otherwise you'd have filenames like myfile__000__001__002__003.jpg)
$previous_tail = str_pad((string) $i-1, 3, "0", STR_PAD_LEFT);
$new_filename = str_replace('__'.$previous_tail,"",$new_filename);
}
$new_filename = str_replace('.'.$fileinfos['extension'],"",$new_filename); // Deletes the extension
$new_filename = $new_filename.'__'.$tail.'.'.$fileinfos['extension']; // Append our tail and the extension
$new_filepath = 'myfiles/music/'.$new_filename; // Crea il nuovo percorso
$i++;
}
copy('my_temp_directory/'.$new_depured_filename, $new_filepath); // Finally we copy the file to its destination directory
unlink('my_temp_directory/'.$new_depured_filename); // and delete the temporary one
Used functions:
strtolower
preg_replace
copy
file_exists
str_pad
pathinfo
str_replace
unlink
To check if a file exists, you can use the file_exists function.
To cut the filename, you can use the pathinfo function.
I use
$file_name = time() . "_" . $uploaded_file_name;