secured file in storage laravel - laravel

i am uploading file in storage like this :
/storage/uploads/contract/19/12199/document.pdf
now i need to to allow only authenticated user to see those document , i use this route :
Route::get('/storage/{pathToFile}', function($pathToFile) {
if (auth()->user()) {
return response()->file($pathToFile);
} else {
return 'Nope, sorry bro, access denied!';
}
});
this didn't work , still all files can be acceded even if user not logged in .
any idea ?
thanks

Did you symlink the public folder to storage folder? If so it would still be accessible because default public entrypoint would be "public" folder so "[host]/storage" would be available in that folder.
What I did in the past was use S3 driver and set file visibility to private then use:
public function get($path, $image)
{
$file = Storage::disk('s3')->get("private/images/". $path. "/" . $image);
return response($file, 200)->header('Content-Type', 'image/png');
}
In your case this would be changed to:
if (auth()->user()) {
$file = Storage::disk('s3')->get($pathToFile);
return response()->file($file);
} else {
return 'Nope, sorry bro, access denied!';
}
Note: S3 driver supports multiple storage solutions: https://flysystem.thephpleague.com/v1/docs/adapter/aws-s3-v2/

Related

unlink(assets/images/profile/1649308242.png): No such file or directory

error after deploy my laravel app to server
my code works fine on my loacal machine but after upload it to the server i got this error
if($this->newimage)
{
if($this->image)
{
unlink('assets/images/profile/'.$this->image);
}
$imageName = Carbon::now()->timestamp . '.' . $this->newimage->extension();
$this->newimage->storeAs('profile',$imageName);
$user->profile->image = $imageName;
}
The address of a file should be an absolute path. I don't know where is your assets directory but in the case of being in your Laravel app root, this would be the solution:
unlink(base_path('assets/images/profile/'.$this->image));
you can set your storage directory instead of public
$storePath = storage_path('app/public/'.$this->image);
if (file_exists($storePath)) {
Storage::disk('public')->delete($this->image);
}
use the helper asset('path/to/file')
e.g.
if this is your image path public/assets/images/profile/1649308242.png.
unlink(asset('assets/images/profile').'/'.$this->image);

delete old image while updating the field

I am doing CRUD operations for images. when I am doing the update operation image gets updated but the old image doesn't delete. The following code updates only the file name in the database but I need to remove the old image from the destination folder too while updating else the folder size will become too large. Any ideas would be great. Here my code.
<input type="file" name="profileimage" value="{{ isset($editabout) ? $editabout->profileimage : '' }}" class="custom-file-input" id="exampleInputFile">
Here is my controller
public function update(updateAboutusProfile $request, AboutUs $about)
{
$data=$request->only(['profiletext']);
if($request->hasFile('profileimage')){
$profileimage = $request->profileimage->store('aboutus', 'public');
$oldimage = $about->profileimage;
Storage::delete($oldimage);
$data['profileimage'] = $profileimage;
}
$about->update($data);
toastr()->success('Profile updated successfully');
return redirect(route('about.index'));
//
}
What can be the error I need to resolve,
thank you
Try setting the disk you used to store the file
Storage::disk('public')->delete($oldimage);
Delete image from your server, you have to reference location of file in directory server, means you could not reference by url link to delete it.
Laravel file is locate in public folder.
Example: your files are located in public/images
$image_path = "/images/filename.ext"; // Value is not URL but directory file path
if(File::exists($image_path)) {
File::delete($image_path);
}
Enjoy ;)
You should save the path of the file to the database and then simply remove it using \Storage::delete() facade.
Store image using hash name
if($request->hasFile('profileimage')){
$store_path = 'aboutus';
$profileimage = $request->profileimage->store($store_path,'public');
$oldimage = $about->profileimage;
$file_address = $store_path.'/'.$request->profileimage->hashName();
\Storage::disk('public')->delete($oldimage);
$data['profileimage'] = $file_address;
}
Store image using original name
if($request->hasFile('profileimage')){
$store_path = 'aboutus';
$profileimage = $request->profileimage->storeAs($store_path, $uploadedFile->getClientOriginalName(),'public');
$oldimage = $about->profileimage;
$file_address = $store_path.'/'.$request->profileimage->getClientOriginalName();
\Storage::disk('public')->delete($oldimage);
$data['profileimage'] = $file_address;
}
Delete the old image while updating
public function update(Request $request, $id)
{
// other updates
if ($request->hasFile('image')) {
//delete old image if exist
if (File::exists(public_path($oldImage))) {
File::delete(public_path(oldImage));
}
//new image process
}
}

Zipping and downloading Amazon S3 bucket files and folders in Laravel

Is there a way to zip and download files and folders which are in Amazon S3 bucket, together in Laravel? I Want to zip the three folders and one file in the picture together and download it
Here's a half baked solution in a route file. Hope it helps.
https://flysystem.thephpleague.com/docs/adapter/zip-archive/
composer require league/flysystem-ziparchive
I put this in routes/web.php just to play with.
<?php
use Illuminate\Support\Facades\Storage;
use League\Flysystem\Filesystem;
use League\Flysystem\ZipArchive\ZipArchiveAdapter;
Route::get('zip', function(){
// see laravel's config/filesystem.php for the source disk
$source_disk = 's3';
$source_path = '';
$file_names = Storage::disk($source_disk)->files($source_path);
$zip = new Filesystem(new ZipArchiveAdapter(public_path('archive.zip')));
foreach($file_names as $file_name){
$file_content = Storage::disk($source_disk)->get($file_name);
$zip->put($file_name, $file_content);
}
$zip->getAdapter()->getArchive()->close();
return redirect('archive.zip');
});
You'll definitely want to do something different than just plopping it in the public dir. Maybe stream it out straight out as a download or save it somewhere better. Feel free to post comment/questions and we can discuss.
I did it the following way after looking at some solutions by streaming the zip directly to the client by using https://github.com/maennchen/ZipStream-PHP :
if ($uploads) {
return response()->streamDownload(function() use ($uploads) {
$opt = new ArchiveOptions();
$opt->setContentType('application/octet-stream');
$zip = new ZipStream("uploads.zip", $opt);
foreach ($uploads as $upload) {
try {
$file = Storage::readStream($upload->path);
$zip->addFileFromStream($upload->filename, $file);
}
catch (Exception $e) {
\Log::error("unable to read the file at storage path: $upload->path and output to zip stream. Exception is " . $e->getMessage());
}
}
$zip->finish();
}, 'uploads.zip');
}

Laravel Collective SSH results

I am performing SSH in Laravel whereby I connect to another server and download a file. I am using Laravel Collective https://laravelcollective.com/docs/5.4/ssh
So, the suggested way to do this is something like this
$result = \SSH::into('scripts')->get('/srv/somelocation/'.$fileName, $path);
if($result) {
return $path;
} else {
return 401;
}
Now that successfully downloads the file and moves it to my local server. However, I am always returned 401 because $result seems to be Null.
I cant find much or getting the result back from the SSH. I have also tried
$result = \SSH::into('scripts')->get('/srv/somelocation/'.$fileName, $path, function($line){
dd( $line.PHP_EOL);
});
But that never gets into the inner function.
Is there any way I can get the result back from the SSH? I just want to handle it properly if there is an error.
Thanks
Rather than rely on $result to give you true / false / error, you can check if the file was downloaded successfully in another way:
// download the file
$result = \SSH::into('scripts')->get('/srv/somelocation/'.$fileName, $path);
// see if downloaded file exists
if ( file_exists($path) ) {
return $path;
} else {
return 401;
}
u need to pass file name also like this in get and put method:
$fileName = "example.txt";
$get = \SSH::into('scripts')->get('/remote/somelocation/'.$fileName, base_path($fileName));
in set method
$set = \SSH::into('scripts')->set(base_path($fileName),'/remote/location/'.$fileName);
in list
$command = SSH::into('scripts')->run(['ls -lsa'],function($output) {
dd($output);
});

"Could not determine temp directory, please specify a cache_dir manually"

Magento admin throws an exception:
Could not determine temp directory, please specify a cache_dir manually
It is fresh instalation on new hosting package.
Usually it will happen in shared web hosting, but also some times on individual server, if the permission of tmp folder is set wrong.
Many people suggest to modify the file:
/lib/Zend/Cache/Backend/File.php to fix this problem. However, it may be a trap when you upgrade your Magento, as this file resides as core file of Magento. I recommend to use Magento's override feature.
Firstly, copy /lib/Zend/Cache/Backend/File.php to /app/code/local/Zend/Cache/Backend/File.php.
Then on line 91 or near this line, you will find:
'cache_dir' => null,
Change to:
'cache_dir' => "var/tmp/",
You can change the cache folder wherever you want.
Now create a directory named tmp(or whatever name you have given above) under var folder and change the permission to 777 if necessary.
This is only the permission issue. Just set the 777 permission to the cache directory and you are all done. try it.
For more details you can follow the link.
When ever you set the permission be sure it is recurrsively set..
chmod 777 -R /var/cache
this is the function
public function getTmpDir()
{
$tmpdir = array();
foreach (array($_ENV, $_SERVER) as $tab) {
foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
if (isset($tab[$key])) {
if (($key == 'windir') or ($key == 'SystemRoot')) {
$dir = realpath($tab[$key] . '\\temp');
} else {
$dir = realpath($tab[$key]);
}
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
}
}
$upload = ini_get('upload_tmp_dir');
if ($upload) {
$dir = realpath($upload);
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
if (function_exists('sys_get_temp_dir')) {
$dir = sys_get_temp_dir();
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
// Attemp to detect by creating a temporary file
$tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
if ($tempFile) {
$dir = realpath(dirname($tempFile));
unlink($tempFile);
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
if ($this->_isGoodTmpDir('/tmp')) {
return '/tmp';
}
if ($this->_isGoodTmpDir('\\temp')) {
return '\\temp';
}
Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually');
}
defined in file lib/Zend/Cache/Backend.php
http://www.webtechnologycodes.com/magento-error-could-not-determine-temp-directory-please-specify-a-cache_dir-manually/
Create tmp folder in root of your magento installation with 777 permissions.
Open lib/Zend/Cache/Backend/File.php
Find $_options property and change line: 'cache_dir' => null, to 'cache_dir' => 'tmp',
Refresh page.
Create an info.php and check for the path beneath upload_tmp_dir to be writable for the webserver.
<?php phpinfo();
Otherwise set the path in your hosting environment.
Beware that this setting can not be placed within .htaccess files but some hosters allow individual php.ini files to be placed in your docroot:
upload_tmp_dir = /path/to/docroot/var/tmp/

Resources