Laravel Symoblic link not working on shared hosting - laravel

I modified the using filesystem configuration as
'local' => [
'driver' => 'local',
'root' => public_path('images'),
'throw' => false,
],
So on local system, I'm storing the all the files in public directory
localhost:8000/public/images
by using file upload
$this->logo->storeAs('brand', 'abc.jpg');
I can directly access images using
url('images')
but when i upload my project to live, images are not displaying. I tried and executed the following route, but fail to load images on live server
Route::get('/link', function () {
$target = public_path();
$link = $_SERVER['DOCUMENT_ROOT'] . '/new';
if (symlink($target, $link))
die("SUCCESS");
else
die("ERROR");
});

Related

Unit testing in laravel using filesystems

I'm doing unit testing using the filesystems config. I want to map my file system disk to a testing directory where I will put my files(JSON, Excel, txt) to be used by the application for testing purposes. I don't want to use fake directories as I need to put the file in the 'import' location.
filesystems.php:
'disks' => [
'import' => [
'driver' => 'local',
'root' => '/import/clientname',
'visibility' => 'private'
],
];
In the application, here is the function which i want to test:
public function importFile(){
$filesystem = Storage::disk('import');
...
}
The solution I was thinking is to use this location for my testing:
Is there a way to implement this solution?
Yes, you can, for example, upload file with each of your disks, then assert if file exist in that directory.
Example of unit test for upload image with form:
public function testStorage()
{
$file = UploadedFile::fake()->image('File10.png');
$response = $this->post(route("save.image"), [
'file' => $file,
]);
$response
->assertStatus(200)
->assertSessionHasNoErrors();
Storage::disk('local')->assertExists("/images/" . $file->name);
}

Laravel server, upload to public_html rather than upload in project folder

I've been trying surfing around this site looking for answers, but nothing works for me, i want to upload an image that save in public_html folder, instead of saving it in project folder (i seperate the project folder and put all public file in public_html folder). Already bind the public.path but it returns to my project folder, not public_html one.
My image upload controller
public static function uploadSubmit($request, $type, $for)
{
if($request->hasFile('photos'))
{
$allowedfileExtension=['jpg','png'];
$files = $request->file('photos');
foreach($files as $file)
{
$extension = $file->getClientOriginalExtension();
$check=in_array($extension,$allowedfileExtension);
//dd($check);
if($check)
{
$idx = Image::create([
'type' => $type,
'ids' => $for,
'ext' => $extension,
])->id;
$filename = $idx . '.' . $file->getClientOriginalExtension();
$filename = $file->storeAs(public_path('images/'), $filename);
}
}
}
}
i already do the public path bind like this in public_html/index.php
$app->bind('path.public', function() {
return __DIR__;
});
Thank you!
First, add config to filesystem.php on config folder:
'disks' => [
...
'public_html' => [
'driver' => 'local',
'root' => public_path(),
'visibility' => 'public',
],
...
],
Second, store image with code:
$file->storeAs('images', $filename, 'public_html')
P/S: Remember to configure the correct path for the public_html directory:
$app->bind('path.public', function(){
return __DIR__.'/../../public_html';
});
The public disk is intended for files that are going to be publicly accessible. By default, the public disk uses the local driver and stores these files in storage/app/public.
When using the local driver, all file operations are relative to the root directory defined in your filesystems configuration file. By default, this value is set to the storage/app directory. Therefore, the following method would store a file in storage/app/file.txt:
Storage::disk('local')->put('file.txt', 'Contents');
Or in your case in storage/app/images/file.txt
$file->storeAs(public_path('images/'), $filename);
You can change where these files are stored by changing the filesystems configuration file.
'local' => [
'driver' => 'local',
'root' => public_path(),
],

Illuminate\Contracts\Filesystem\FileNotFoundException in Laravel 5.6 using Storage facade

This code is returning an strange error:
$file = Storage::get(Storage::disk('notas_xml')->path('') . 't.txt');
As you can see the file does exist.
Get the file directly from the disk
$exists = Storage::disk('notas_xml')->exists('t.txt');
if ($exists) {
$file = Storage::disk('notas_xml')->get('t.txt');
}
And if you didn't setup notas_xml disk in filesystems.php
$file = Storage::get('public/arquivos/notas_xml/t.txt');
And to use your code, you need to setup a disk like so in config/filesystems.php
'notas_xml' => [
'driver' => 'local',
'root' => storage_path('app/public/arquivos/notas_xml'),
'url' => env('APP_URL') . '/storage',
'visibility' => 'public',
],
And get the file simply like this
$file = Storage::disk('notas_xml')->get('t.txt');
You need to get the file as below code:
Storage::disk('notas_xml')->has('t.txt');
Above has method may be used to determine if a given file exists on the disk:
Please read documentation https://laravel.com/docs/5.1/filesystem#retrieving-files
To better understand all this... The trick is in: config/filesystems.php
If you have this code (which is the default value of Laravel in Github)
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
This Facade Storage will act in the folders
root_laravel_project/storage/app
So if you want to check if an "israel.txt" file exists
if( Storage::exists('israel.txt') ){
echo "File found. And it exists on the path: root_laravel_project/storage/app/israel.txt";
}
Remember that up to this point it has nothing to do with the symbolic link php artisan storage: link
This symbolic link is only to make a folder called "public" within the "storage" folder be part of the public access through HTTP
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
Then at the time of doing the sym. You can access the files by http (which are public for any user)
This example assumes that you are using a virtual host (and if not, you must do it as a recommendation for work better locally)
http:// root_laravel_project.test/storage/israel-alvarez.txt
Or so that it is better understood as in the old school without a virtual host
http:// localhost/public/storage/israel-alvarez.txt
Then these urls will look inside your folder
root_laravel_project/storage/app/public/israel-alvarez.txt
Laravel's documentation is somewhat brief and can be confusing regarding this issue. But you just have to remember that one thing is to access through the "storage Facade" (which is the correct way to upload and verify if there are files) and another thing is to access through the http (through url) which is the symbolic link (which is the treatment you already give to users to download files or see if it is a PDF for example).
I hope it helps. Good day

Laravel upload without form and request functionality

I want to run a scheduler (CRON) that reads a csv file every minute and imports it into a database.
I want to grab the file from a predefined directory on my windows directory system and upload it into the storage area in Laravel on my host server.
I created a test function to read the contents of a directory. I get an error
'The "C:/Users/alfre/code" directory does not exist.'.
What is the correct way to upload files with a scheduler?
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'odoofiles' => [
'driver' => 'local',
'root' => '\Users\alfre\code\storage\csv',
],
I could not find an answer yet on the web.
you should not use absolute paths from windows.
try placing the cvs folds in in the storage folder and try
on your computer it will be something like C:/Users/alfre/code/storage/csv
public function test()
{
$files = File::allFiles(storage_path('csv'));
foreach ($files as $file)
{
echo (string)$file, "\n";
}
}

Wrong path when downloading in Backpack CRUD view

i added an upload field in my CRUD Controller.
Upload works fine and file gets loaded in my /storage/private directory.
Here is filesystems.php file:
'private' => [
'driver' => 'local',
'root' => storage_path('private')
],
Here are my custom functions in the File.php Model:
public static function boot()
{
parent::boot();
static::deleting(function($file) {
\Storage::disk('private')->delete($file->file);
});
}
public function setFileAttribute($value)
{
$attribute_name = "file";
$disk = "private";
$destination_path = "";
// Cifratura del file
file_put_contents($value->getRealPath(), file_get_contents($value->getRealPath()));
$this->uploadFileToDisk($value, $attribute_name, $disk, $destination_path);
}
And here is my FileCRUDController.php code:
$this->crud->addField(
[ // Upload
'name' => 'file',
'label' => 'File to upload',
'type' => 'upload',
'upload' => true,
'disk' => 'private'
]);
When i try to download the file, however, it tries to fetch it from http://localhost:8000/storage/myfile.png instead of http://localhost:8000/storage/private/myfile.png
What i'm doing wrong? Thank you very much.
I would also like to know if there is a way to hook a custom function instead downloading the file directly from the CRUD view. My files are encrypted and i need a controller that cares about decrypting before sending the files to the user.
Method url() is still not usable for the files are placed in subdirectories.
You may also use the storage_path function to generate a fully qualified path to a given file relative to the storage directory:
$app_path = storage_path('app');
$file_path = storage_path('app/file.txt');
In reference to Issue #13610
The following works for version 5.3:
'my-disk' => [
'driver' => 'local',
'root' => storage_path(),
'url' => '/storage'
],
\Storage::disk('my-disk')->url('private/myfile.png')
this should return "/storage/private/myfile.png"

Resources