php tempnam(sys_get_temp_dir(), $fileName); saves in wierd name - php

i'm using to tempnam(sys_get_temp_dir(), $fileName); to temporary save an image in the /private/var/tmp.
The images are being save with a weird text after them
For example:
10153114610662388_1434185314.jpggd5Wc6
After i'm saving them, I'm uploading them to facebook and it gives me the following error {"error":"(#324) Requires upload file"} and I think it because of that.

From the PHP documentation (http://php.net/manual/en/function.tempnam.php) for tempnam:
string tempnam ( string $dir , string $prefix )
dir The directory where the temporary filename will be created.
prefix The prefix of the generated temporary filename.
So the second parameter is a prefix for the filename, not the filename that it will use. tempnam makes sure that the filename is unique (so you don't overwrite another temp file) - and that's what the "weird text" at the end is for.
If you want to save the file with the filename you already have just use it directly - but understand that if a file with that name already exists you'll overwrite it.

Related

Laravel rename file

I'm trying to rename a file in laravel 5.6
This works fine when I'm physically renaming the file, but when I'm just changing case - It throws an error:
League\Flysystem\FileExistsException: File already exists at path
Example
old path: Music/The Corrs/The Corrs - What Can I Do.mp3
new path (DO): Music/The Corrs/The Corrs - What Can I DO.mp3
Code
Storage::disk($disk)->move($old, new);
How can I work around this so I can rename/move files if just the case is changing?
On Windows, case doesn't matter for file names. So files with the names uppercase.txt and UPPERCASE.txt are the same, but it is impossible to have two files with the same name in a folder.
When renaming, the file is actually "moved" to another name. However the file already exists, so you get an error.
I would recommend to store the files in a temp folder first to rename or use a temporary name for the files before renaming.
Off the cuff solution
$oldPath = "Music/The Corrs/The Corrs - What Can I Do.mp3";
$newPath = "Music/The Corrs/The Corrs - What Can I DO.mp3";
$paddedPath = str_replace(" ", "##padding##", $oldPath);
//move from old path to padded path
Storage::move(
$oldPath,
$paddedPath,
);
//move from padded path to new
Storage::move(
$paddedPath,
$newPath
);

Replace save files if from same User

I have a directory called resale_certificates where I save files to but encrypt the name using parts of their email and codes assigned to them.
NOTE: The encryption is the same every time but unique to each user!
When they upload image.png it will save the file to theirEncrypt.png
If they upload another image.png it will replace theirEncrypt.png
However when they upload image.jpg now there will be theirEncrypt.jpg and theirEncrypt.png in the resale_certificates directory.
What is the best way to handle this? I'm looking for advice and open to changing how I'm saving it or tricks I could do to prevent this!
Thank You!
Well, you could use an image library to transform their uploaded image to whatever format you want, i.e. if they upload a .JPG you can use image libraries like Imagick or GD to output a .PNG file and upload those.
However, if you don't mind either the .JPG or .PNG ( or .GIF for that matter) you can scan the directory with PHP to look for all files ( can be really intensive though! ) to look for files with the name given.
For example:
<?php
foreach( scandir('/path/to/resale_certificates/') as $file ){
if( $file != '.' && $file != '..'){
// explode so we remove the last extension path ( not type safe ! )
$arguments = explode('.', $file);
// store the last part
$ext = end($arguments);
// pop the extension from the $arguments array so we are left
// with whatever was left
array_pop($arguments);
// concatenate the $arguments into a single string again
$filename = implode('.', $arguments);
// now we can check the filename again
if( $filename == $theirEncrypt){
unlink('/path/to/resale_certificates/' . $filename . '.' . $ext);
}
}
}
edit:
the $file is a string from the $files array returned by the scandir(); function. The single and double dot are a ways to navigate to the current (.) and the parent (..) directory and are therefore symlinks. Another option would be to check if the $file is actually a file. You could replace the comparison line with a is_file('/path/to/resale_certificates/' . $file) to check if it's a file or a symlink ( like the . and the .. ) but it's even more intensive then to check string comparison. In your usecase it is not neccesary.
On a related note, this is quite intensive, depending on the number of clients and certificates you have, you could, as an alternative, store the filename to storage (i.e. database or something similiar) and just unlink the file find there, this would save you to iterate over each file and simply unlink the file directly.
If you know a name of previously uploaded image then you can do the following before saving a new image:
<?php
$previousImageName = 'theirEncrypt.png';
unlink(APP_DIR . "/resale_certificates/" . $previousImageName);

Get file from temp after confirm with PHP/Laravel

I have a form with a file to uplaod. All works find. But I don't want to move the file directly into a folder.
After submit I show a confirm page and there I show the uploaded file with
header('Content-Type: image/x-png');
$file = file_get_contents(\Illuminate\Support\Facades\Input::file('restImg'));
$imgType = \Illuminate\Support\Facades\Input::file('restImg')->guessClientExtension();
echo sprintf('<img src="data:image/png;base64,%s" style="max-height: 200px"/>', base64_encode($file));
This works fine. After the confirmation I like to move the file to a folder. How can I move the file after the confirmation? The Input::get('file') is not available anymore.
You will have to store the file in the initial upload somewhere temporarily other than the default tmp directory.
The documentation for PHP file uploads says:
The file will be deleted from the temporary directory at the end of the request if it has not been moved away or renamed
This means that moving onto the next request, the file will no longer be available.
Instead, move it to your own custom temp directory or rename it to something special, then keep the filename in the $_SESSION to persist it to the next request.
For Laravel, this should mean putting it in the /storage directory with something like this:
// Get the uploaded file
$file = app('request')->file('myfile');
// Build the new destination
$destination = storage_path() . DIRECTORY_SEPARATOR . 'myfolder';
// Make a semi-random file name to try to avoid conflicts (you can tweak this)
$extension = $file->getClientOriginalExtension();
$newFilename = md5($file->getClientOriginalName() . microtime()).'.'.$extension;
// Move the tmp file to new destination
app('request')->file('myfile')->move($destination, $newFilename);
// Remember the last uploaded file path at new destination
app('session')->put('uploaded_file', $destination.DIRECTORY_SEPARATOR.$newFilename);
Just remember to unlink() the file after the second request or do something else with it, or that folder will fill up fast.
Additional Reference:
http://api.symfony.com/2.7/Symfony/Component/HttpFoundation/File/UploadedFile.html

verify file name at upload with only a given file name

How can i verify a file name when uploading e.g. xyz.xlsx for this specific file and no other? Thus the file is uploaded if and only if its name is xyz with extension xlsx "xyz.xlsx".
If I understand what your looking for, just grab the filename and test it.
Example:
if($_FILES['uploadedfile']['name'] == "xyz.xlsx")
http://us2.php.net/manual/en/features.file-upload.post-method.php
When you do an upload with PHP, you get a $_FILES array (kind of like $_POST). You'll find the original filename in $_FILES['userfile']['name']. You can verify that as MyGlass suggests in his answer.
if($_FILES['uploadedfile']['name'] == "xyz.xlsx")
Additionally, codeignitor provides a file upload class that can be used to eliminate some of the boiler plate of file uploads here: http://ellislab.com/codeigniter/user-guide/libraries/file_uploading.html
Use $this->upload->data() to get the array with the filename info (the key is 'file_name').
$data = $this->upload->data();
if($data['file_name'] == "xyz.xlsx")

I made an upload script in PHP. How do I avoid overwriting files?

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;

Categories