How to Check file exists in Laravel - php

I have a Laravel Controller Function file_fetch()
public function file_fetch(Request $request) {
$file = request('routename');
$destinationPath = public_path('/folder/'.$file);
if(!File::exists($destinationPath)){
$content = File::get($destinationPath);
return view('filefetch', compact('file','content'));
}
else {
return redirect('/')->witherrormessage('NO such File Exists');
}
}
This works if i check for file public/folder/app/index.html and if i check for public/newfolder (newfolder doesnt exist) and hence it executes else function and redirects with error message, but if i search for public/folder/app/ I havent specified the file name, but the directory exists, hence the if(!File::exists($destinationPath)) function is getting executed!
i want to check just and files inside the directory and even if the directory exists, if file is not present, throw a error message, saying file doesnt exists.

add one more additional condition to check given path is file but not a directory
public function file_fetch(Request $request) {
$file = request('routename');
$destinationPath = public_path('/folder/'.$file);
if(!File::exists($destinationPath) && !is_dir($destinationPath)){
$content = File::get($destinationPath);
return view('filefetch', compact('file','content'));
}
else {
return redirect('/')->witherrormessage('NO such File Exists');
}
}

You can probably fix your code by validating the routename input such that it will never be empty (and have a certain file extension maybe?)
, which is nice to do anyhow.
If that fails, you can try File::isDirectory($dir) which basically calls is_dir(...).
Note that it might give you more control on your storage solution if you use the Storage::disk('public') functionalities from Laravel. The API is a bit different but there's a wide range of probabilities associated with it. Read more about that here: https://laravel.com/docs/8.x/filesystem#introduction.

If you in different/multiple buckets.
//Do not forget to import
use Illuminate\Support\Facades\Storage;
if (Storage::disk('s3.bucketname')->exists("image1.png")) {
}

Related

laravel - saving and accessing an uploaded file

I am studying some laravel code that I downloaded and I am getting some problem.
This supposed to be the functions to save,delete and download the files but the problem is.
The files are being saved in a folder named with a number on "storage\app\public\project-files\" (i.e. storage\app\public\project-files\11), both destroy and download methods are referencing different paths, I tried to change but didn't worked, download show FileNotFoundException and destroy just remove from the database but not from the folder
So is this code wrong? How It supposed to be?
I've read about using artisan:link but seems odd to me run this command every time I want upload a file to make a link
PS. I cheched the routes, so the methods are being called
Thanks
public function store(Request $request)
{
if ($request->hasFile('file')) {
$file = new ProjectFile();
$file->user_id = $this->user->id;
$file->project_id = $request->project_id;
$request->file->store('public/project-files/'.$request->project_id);
$file->filename = $request->file->getClientOriginalName();
$file->hashname = $request->file->hashName();
$file->size = $request->file->getSize();
$file->save();
$this->project = Project::find($request->project_id);
return view('project-files');
}
public function destroy($id)
{
$file = ProjectFile::find($id);
File::delete('storage/project-files/'.$file->project_id.'/'.$file->hashname);
ProjectFile::destroy($id);
$this->project = Project::find($file->project_id);
return view('project-files');
}
public function download($id) {
$file = ProjectFile::find($id);
return response()->download('storage/project-files/'.$file->project_id.'/'.$file->hashname);
}
You are storing files in storage so i assume you have uploaded image in the following path
project\storage\app\public\project-files
if this is the path then you can delete using
Storage::delete('public/project-files/1.JPG');
for Downlaoding file
$path= storage_path('app/public/project-files/3.JPG');
return response()->download($path);

Save file to memory and later write back

I wish to read a file using PHP, and later write it to a directory which doesn't exist at the time of reading the file. I can't create the directory first as described below. I do not wish to save it in a temporary directory to prevent possible overwrites. Am I able to read the file, save it in memory, and later write the file?
WHY I WISH TO DO THIS: I have the following method which empties a directory. I now have a need to do so but keep one file in the root of the emptied directory. I recognize I could modify this method to do so, but I rarely need to do so, and may wish another approach. Instead, before calling this method, I would like to copy the file in question, empty the directory, and then put it back.
/**
* Empty directory. Include subdirectories if $deep is true
*/
public static function emptyDir($dirname,$deep=false)
{
$dirname=(substr($dirname, -1)=='/')?$dirname:$dirname.'/';
if(!is_dir($dirname)){return false;}
// Loop through the folder
$dir = dir($dirname);
while (false !== $entry = $dir->read())
{
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
elseif(is_file($dirname.$entry)) {
unlink($dirname.$entry);
}
elseif($deep && is_dir($dirname.$entry)){
self::deltree($dirname.$entry);
}
}
// Clean up
$dir->close();
return true;
}
Provided this is all done withing the same request, then yes you can.
Just save the file contents to a variable, then write it back again:
$temp = file_get_contents('path/to/file.ext');
className::emptyDir($dir);
file_put_contents('path/to/file.ext', $temp);
Yes, it could be done. Just add a property to your class. So in your class property, there will be the content of the file, while the object is exists, and it did set. It could be a class variable (static) also, so you do not need to instantiate if you do not want.
class anything {
var $fileContent = '';
public static function emptyDir($dirname,$deep=false) {
//....
}
public function setFileContent($fileOrUrlToRead) {
$this->fileContent = file_get_contents($fileOrUrlToRead);
}
public function saveFile($fileName) {
file_put_contents($fileName, $this->fileContent);
}
}
$anything = new anything();
$anything->setFileContent('url_or_path_of_file_to_get');
anything::emptyDir('./media/files/');
$anything->saveFile('./media/files/something.txt');
You can use the session to save the needed information.

$_FILES empty when uploading Magento package

I am trying to install a Magento package, but I get No file was uploaded
Its coming from this code because $_FILES is an empty array in /downloader/Maged/Controller.php
/**
* Install uploaded package
*/
public function connectInstallPackageUploadAction()
{
if (!$_FILES) {
echo "No file was uploaded";
return;
}
if(empty($_FILES['file'])) {
echo "No file was uploaded";
return;
}
$info =& $_FILES['file'];
if(0 !== intval($info['error'])) {
echo "File upload problem";
return;
}
$target = $this->_mageDir . DS . "var/" . uniqid() . $info['name'];
$res = move_uploaded_file($info['tmp_name'], $target);
if(false === $res) {
echo "Error moving uploaded file";
return;
}
$this->model('connect', true)->installUploadedPackage($target);
#unlink($target);
}
It might be worth noting that product uploads work fine.
The only log output I get is
2014-07-03T18:44:15+00:00 ERR (3): Warning: array_key_exists() expects parameter 2 to be array, null given in /var/www/vhosts/example.com/httpdocs/app/code/core/Mage/Captcha/Model/Observer.php on line 166
exception.log was empty
Make sure that your var folder in magento installation is fully writable. 777 permission. All folders and files.
You can try uploading a small dummy file first to check if the error stays the same.
There is a file upload limit which might be reached.
File upload often fails due to upload_max_filesize or post_max_size being too small as mentioned in Common Pitfalls section of the PHP documentation.
Use firebug in firefox to check if your form does has enctype="multipart/form-data".
Check the user group it was created with,
To explain, recently I had some file saving issues. Turned out I had created the folder using the Root user for the server, and the CPanel user ( the one php was running under ) didn't have permission to write in folders owned by the Root account, even when setting the permissions to 777.
Just a thought.
First check if your installation is configured properly
see#http://php.net/manual/en/features.file-upload.common-pitfalls.php
Also, if you upload with PUT/xhr the file is on the input stream
$in = fopen('php://input','r');
see#http://php.net/manual/en/features.file-upload.put-method.php and https://stackoverflow.com/a/11771857/2645347,
this would explain the empty $FILES array, in case all else is ok and the upload works via xhr/PUT.
$_FILES is an associative array of items uploaded to the current script via the HTTP POST method. All uploaded files are stored in $HTTP_POST_FILES contains the same initial information, but is not a superglobal. So, ... be sure that method is POST
Always check that your form contains correct enctype:
<form ... enctype="multipart/form-data"> ... </form>
Sometimes happens that when someone upload multiples file, $_FILES return empty. This could happen when I select files that exceed some size. The problem can be in the POST_MAX_SIZE configuration.
On
app/code/core/mage/captcha/model/observer.php
change
public function checkUserLoginBackend($observer)
{
$formId = 'backend_login';
$captchaModel = Mage::helper('captcha')->getCaptcha($formId);
$loginParams = Mage::app()->getRequest()->getPost('login');
$login = array_key_exists('username', $loginParams) ? $loginParams['username'] : null;
if ($captchaModel->isRequired($login)) {
if (!$captchaModel->isCorrect($this->_getCaptchaString(Mage::app()->getRequest(), $formId))) {
$captchaModel->logAttempt($login);
Mage::throwException(Mage::helper('captcha')->__('Incorrect CAPTCHA.'));
}
}
$captchaModel->logAttempt($login);
return $this;
}
to
public function checkUserLoginBackend($observer)
{
$formId = 'backend_login';
$captchaModel = Mage::helper('captcha')->getCaptcha($formId);
$login = Mage::app()->getRequest()->getPost('username');
if ($captchaModel->isRequired($login)) {
if (!$captchaModel->isCorrect($this->_getCaptchaString(Mage::app()->getRequest(), $formId))) {
$captchaModel->logAttempt($login);
Mage::throwException(Mage::helper('captcha')->__('Incorrect CAPTCHA.'));
}
}
$captchaModel->logAttempt($login);
return $this;
}
Your issue is:
"Captcha Observer throws an error if login in RSS feed" issue #208
or if you wish you could only replace the variable $login to be like this:
$login = array_key_exists('username', array($loginParams)) ? $loginParams['username'] : null;
You may try out below points.
Use Magento Varien File Uploaded Classes to Upload the files.
Magento File Uploader
1) Check enctype="multipart/form-data" in your form.
2) Use Magento Form Key in your form.
3) Use Varien file uploader to upload your files using below links answers.

Creating a folder when I run file_put_contents()

I have uploaded a lot of images from the website, and need to organize files in a better way.
Therefore, I decide to create a folder by months.
$month = date('Yd')
file_put_contents("upload/promotions/".$month."/".$image, $contents_data);
after I tried this one, I get error result.
Message: file_put_contents(upload/promotions/201211/ang232.png): failed to open stream: No such file or directory
If I tried to put only file in exist folder, it worked. However, it failed to create a new folder.
Is there a way to solve this problem?
file_put_contents() does not create the directory structure. Only the file.
You will need to add logic to your script to test if the month directory exists. If not, use mkdir() first.
if (!is_dir('upload/promotions/' . $month)) {
// dir doesn't exist, make it
mkdir('upload/promotions/' . $month);
}
file_put_contents('upload/promotions/' . $month . '/' . $image, $contents_data);
Update: mkdir() accepts a third parameter of $recursive which will create any missing directory structure. Might be useful if you need to create multiple directories.
Example with recursive and directory permissions set to 777:
mkdir('upload/promotions/' . $month, 0777, true);
modification of above answer to make it a bit more generic, (automatically detects and creates folder from arbitrary filename on system slashes)
ps previous answer is awesome
/**
* create file with content, and create folder structure if doesn't exist
* #param String $filepath
* #param String $message
*/
function forceFilePutContents ($filepath, $message){
try {
$isInFolder = preg_match("/^(.*)\/([^\/]+)$/", $filepath, $filepathMatches);
if($isInFolder) {
$folderName = $filepathMatches[1];
$fileName = $filepathMatches[2];
if (!is_dir($folderName)) {
mkdir($folderName, 0777, true);
}
}
file_put_contents($filepath, $message);
} catch (Exception $e) {
echo "ERR: error writing '$message' to '$filepath', ". $e->getMessage();
}
}
i have Been Working on the laravel Project With the Crud Generator and this Method is not Working
#aqm so i have created my own function
PHP Way
function forceFilePutContents (string $fullPathWithFileName, string $fileContents)
{
$exploded = explode(DIRECTORY_SEPARATOR,$fullPathWithFileName);
array_pop($exploded);
$directoryPathOnly = implode(DIRECTORY_SEPARATOR,$exploded);
if (!file_exists($directoryPathOnly))
{
mkdir($directoryPathOnly,0775,true);
}
file_put_contents($fullPathWithFileName, $fileContents);
}
LARAVEL WAY
Don't forget to add at top of the file
use Illuminate\Support\Facades\File;
function forceFilePutContents (string $fullPathWithFileName, string $fileContents)
{
$exploded = explode(DIRECTORY_SEPARATOR,$fullPathWithFileName);
array_pop($exploded);
$directoryPathOnly = implode(DIRECTORY_SEPARATOR,$exploded);
if (!File::exists($directoryPathOnly))
{
File::makeDirectory($directoryPathOnly,0775,true,false);
}
File::put($fullPathWithFileName,$fileContents);
}
I created an simpler answer from #Manojkiran.A and #Savageman. This function can be used as drop-in replacement for file_put_contents. It doesn't support context parameter but I think should be enough for most cases. I hope this helps some people. Happy coding! :)
function force_file_put_contents (string $pathWithFileName, mixed $data, int $flags = 0) {
$dirPathOnly = dirname($pathWithFileName);
if (!file_exists($dirPathOnly)) {
mkdir($dirPathOnly, 0775, true); // folder permission 0775
}
file_put_contents($pathWithFileName, $data, $flags);
}
Easy Laravel solution:
use Illuminate\Support\Facades\File;
// If the directory does not exist, it will be create
// Works recursively, with unlimited number of subdirectories
File::ensureDirectoryExists('my/super/directory');
// Write file content
File::put('my/super/directory/my-file.txt', 'this is file content');
I wrote a function you might like. It is called forceDir(). It basicaly checks whether the dir you want exists. If so, it does nothing. If not, it will create the directory. A reason to use this function, instead of just mkdir, is that this function can create nexted folders as well.. For example ('upload/promotions/januari/firstHalfOfTheMonth'). Just add the path to the desired dir_path.
function forceDir($dir){
if(!is_dir($dir)){
$dir_p = explode('/',$dir);
for($a = 1 ; $a <= count($dir_p) ; $a++){
#mkdir(implode('/',array_slice($dir_p,0,$a)));
}
}
}

How do I check if I have write permissions in the current path

in php how do I determine whether or not I can create a file in the same path as the script trying to create a file
Unfortunately, all of the answers so far are wrong or incomplete.
is_writable
Returns TRUE if the filename exists and is writable
This means that:
is_writable(__DIR__.'/file.txt');
Will return false even if the script has write permissions to the directory, this is because file.txt does not yet exist.
Assuming the file does not yet exist, the correct answer is simply:
is_writable(__DIR__);
Here's a real world example, containing logic that works whether or not the file already exists:
function isFileWritable($path)
{
$writable_file = (file_exists($path) && is_writable($path));
$writable_directory = (!file_exists($path) && is_writable(dirname($path)));
if ($writable_file || $writable_directory) {
return true;
}
return false;
}
Have you tries the is_writable() function ?
Documentation
http://www.php.net/manual/en/function.is-writable.php
Example:
$filename = 'test.txt';
if (is_writable($filename)) {
echo 'The file is writable';
} else {
echo 'The file is not writable';
}
The is_writable function is good stuff. However, the OP asked about creating a file in the same directory as the script. Blatantly stealing from vlad b, do this:
$filename = __DIR__ . '/test.txt';
if (is_writable($filename)) {
echo 'The file is writable';
} else {
echo 'The file is not writable';
}
See the php manual for predefined constants for the details on __DIR__. Without it, you're going to create a file in the current working directory, which is probably more or less undefined for your purposes.
Use is_writable PHP function, documentation and example source code of this you can find at http://pl2.php.net/manual/en/function.is-writable.php

Categories