How to find file without specific file extension in laravel storage? - php

How to find file by name without specific extension in laravel Storage?
like this "filename.*"
Storage::get("filename.*")
I tried this but seems not to work. It searches for specific file with specific extension.

Storage::get() takes a file path as a parameter and returns the content of a single file identified by this path or throws FileNotFoundException if file can't be found.
Wildcards are not supported in the path - one reason for that could be that there might be multiple files that match the path with wildcards which would break the rule that content of a single file is returned from Storage::get(). Scanning the whole folder would also be much slower, especially with remote storages.
However, you could get what you want using other functionality that Storage facade offers. First, list the content of your storage - that will give you the list of all available files. Then filter the list yourself to get the list of matching files.
// list all filenames in given path
$allFiles = Storage::files('');
// filter the ones that match the filename.*
$matchingFiles = preg_grep('/^filename\./', $allFiles);
// iterate through files and echo their content
foreach ($matchingFiles as $path) {
echo Storage::get($path);
}

Accepted solution works. However I've found this other and I like it more:
$matchingFiles = \Illuminate\Support\Facades\File::glob("{$path}/*.log");
See reference here:
http://laravel-recipes.com/recipes/143/finding-files-matching-a-pattern

Minor change to jedrzej.kurylo's answer and combining wogsland's answer using laravel 8:
'/^filename\./' or '/filename\./' pattern does not work in my case.
// From:
$matchingFiles = preg_grep('/^filename./', $allFiles);
// To:
$allFiles = Storage::disk('yourStorageDisk')->files('folder/path');
$allowedMimeTypes = ['image/jpeg', 'image/png', 'image/webp'];
$matchingFiles = preg_grep('{'.$image.'}', $allFiles);
foreach ($matchingFiles as $path) {
// get real mime type
$contentType = image_type_to_mime_type(exif_imagetype(asset($path)));
// compare it with our allowed mime types
if (in_array($contentType, $allowedMimeTypes)) {
// do something here...
}
}
This way we can fetch files or images safely.

Dont trust what you see. Get inside and get the ext for your file
$pic = 'url/your.file';
$ext = image_type_to_mime_type(exif_imagetype($pic));
$ext = explode('/',$ext);
echo $ext[1];

Related

Iterate thru possible file extension to get the proper extension

I have a folder with many files in various formats eg .jpg, .png, .pdf, .doc etc... The files are on a remote server. I have a json file with list of filenames and its location but missing the extensions.
I want to rebuild the json file and add the proper extension to filename. How can I do this with php? Can anyone give me any ideas how to iterate thru possible extensions to get the right filename + ext on the server.
eg. I have a url like this - http://www.somesite.com/filename. I know on the server the file is pdf but how can I do this programatically for many files which may be different and rename the url?
Any ideas?
Use a For Loop To loop over all current know file extensions and execute a GET request to the $url . $extension and see if the server returns a file.
If the server returns a file, you can break the for loop.
You can nest 2 for loops in each other to do this far all know urls.
Example
$files = [
"http://test.com/test",
"http://test.com/test2"
];
$extensions = [
".jpg",
".docx"
];
foreach ($files as $file)
{
foreach ($extensions as $extension)
{
$foundFile = // Get requests here
if(FILE_IS_FOUND){
// Store file where ever you need it
break;
}
}
}
This example uses a Foreach Loop

get a unknown file name in different dir, php

Here is my directory structure,
C:\xampp\htdocs\..
C:\download\20150923abc.xls //abc is a random value
how can I attach the file 20150923abc.xls in php?
Also, how to change the filename after I got it?
Thanks.
Use the glob ability to find references all files of type .xls and then you can use the file name references as you wish. This sidesteps the issue of you not knowing the specific file name.
$files = glob("c:/download/*.xls");
This will produce an array of all .xls files with their full filepath. If you wish to rename or attach these files then you can do this using the glob reference:
rename($files[0], "c:/download/somenewname.xls");
etc. Read more at:
PHP Glob Function
EDIT:
From Comment below:
foreach (glob( $old_folder."*.xls") as $filename)
{
$names = explode('/', $filename);
$just_file_name = end($names);
echo $just_file_name . "----\n";
$new_folder = dirname(FILE)."\\prm\\att\\";
//rename_win($old_folder, $new_folder);
rename($filename, $new_folder.$just_file_name); <== this line changed.
}
unset($filename);
To fix the above code in your comment, you need to change the incorrect variables referenced (there was no array $files[0]) to the ones used in the foreach loop.

PHP fileupload type check

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';
}

unlink files with a case-insensitive (glob-like) pattern

I have two folders, in one i have the videos and in the second one the configuration files for each video(3 files per video). Now if i want to delete a video i have to delete files by hand.
I found this :
<?php
$filename = 'name.of.the.video.xml';
$term = str_replace(".xml","", $filename);
$dirPath = ("D:/test/");
foreach (glob($dirPath.$term.".*") as $removeFile)
{
unlink ($removeFile);
}
?>
A echo will return:
D:/test/name.of.the.video.jpg
D:/test/name.of.the.video.srt
D:/test/name.of.the.video.xml
Is ok and it help me a lot, but i have a problem here.
Not all files are the same ex:
Name.of.The.video.jpg
Name.Of.The.Video.xml
If i echo the folder looking for that string and is not identic with the $filename will return empty.
So, my question is, how can i make that search Case insensitive?
Thank you.
You are making use of the glob function which is case sensitive. You are using the wrong function therefore to get the list of files.
You should therefore first normalize the filenames in the directory so they all share the same case (e.g. all lowercase). Or you need to use another method to get the directory listing case-insensitive. I suggest the first, however if that is not an option, why don't you glob for all files first and then filter the list of files using preg_grep which allows to specify patterns that are case-insensitive?
Which leads me to the point that it's more practicable to use DirectoryIterator with a RegexIterator:
$filename = 'name.of.the.video.xml';
$term = basename($filename, ".xml");
$files = new DirectoryIterator($dirPath);
$filesFiltered = new RegexIterator($files, sprintf('(^%s\\..*$)i', preg_quote($term)));
foreach($filesFiltered as $file)
{
printf("delete: %s\n", $file);
unlink($file->getPathname());
}
A good example of the flexibility of the Iterators code are your changed requirements: Do that for two directories at once. You just create two DirectoryIterators and append the one to the other with an AppendIterator. Job done. The rest of the code stays the same:
...
$files = new AppendIterator();
$files->append(new DirectoryIterator($dirPath1));
$files->append(new DirectoryIterator($dirPath2));
...
Voilá. Sounds good? glob is okay for some quick jobs that need just it. For everything else with directory operations start to consider the SPL. It has much more power.
Is strcasecmp() a valid function for this? Its a case insensitive str comparison function?
Surely if you know the file name and you can echo it out, you can pass this to unlink()?

PHP include image file with changing filename

I am completely new to PHP so forgive me if this question seems very rudimentry. And thank you in advance.
I need to include a jpg that is generated from a webcam on another page. However I need to include only the latest jpg file. Unfortunately the webcam creates a unique filename for each jpg. How can I use include or another function to only include the latest image file?
(Typically the filename is something like this 2011011011231101.jpg where it stands for year_month_date_timestamp).
Easy way is to get the latest image with the help of the below code
$path = "/path/to/my/dir";
$latest_ctime = 0;
$latest_filename = '';
$d = dir($path);
while (false !== ($entry = $d->read())) {
$filepath = "{$path}/{$entry}";
// could do also other checks than just checking whether the entry is a file
if (is_file($filepath) && filectime($filepath) > $latest_ctime) {
$latest_ctime = filectime($filepath);
$latest_filename = $entry;
}
}
}
// now $latest_filename contains the filename of the newest file
give the source of latest image to <img> tag
Since the images are named via pattern which relates to the date, you should be able to just use:
$imgs = glob('C:\images\*.jpg');
rsort($imgs);
$newestImage = $imgs[0];
This is fairly straightforward, since your file names are in order.
The first thing you need is a list of files in the directory. The readdir (doc) function is what you are looking for. Example script that uses it: http://www.liamdelahunty.com/tips/php_list_a_directory.php
Once you have that, use substr() (doc) to chop off the file name extensions.
You're left with an array of numbers, essentially. From here, do a sort (doc) and specify the SORT_NUMERIC flag. Grab the number on the end, stick a .jpg back on it, and you have the last file.
Alternate Solution: Read the timestamps of files to get the last one. This would generally be a better answer, but perhaps not in your situation if you plan to edit any of the files.
I guess you will have to know a way to determine what the latest image file is called. Maybe you can make a textfile or something where every time a new image is created the webcam writes the latest filename in the text file (so the only text in the text file is the file name of the latest image file if it makes any sense). Of course you will have to have access to the script that generates the php file.
addition to #ken 's post, it's probably sorting alphabetically instead of numerically. perhaps you could try:
$imgs = glob('C:\images\*.jpg');
rsort($imgs, SORT_NUMERIC);
$newestImage = $imgs[0];

Categories