I'm trying to upload a (DomPDF generated) PDF file to Dropbox with the Dropbox driver in Laravel 8. I've installed spatie/flysystem-dropbox and created a DropboxServiceProvider.php with following contents:
<?php
namespace App\Providers;
use Storage;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client;
use Spatie\FlysystemDropbox\DropboxAdapter;
class DropboxServiceProvider extends ServiceProvider
{
public function boot()
{
Storage::extend('dropbox', function ($app, $config) {
$client = new Client([$config['key'], $config['secret']]);
return new Filesystem(new DropboxAdapter($client));
});
}
public function register()
{
//
}
}
The service provider is also added to my config/app providers:
'providers' => [
...
App\Providers\DropboxServiceProvider::class,
...
]
In my config/filesystems I've added the dropbox driver (dropbox app key and secret are also set in .env file):
'dropbox' => [
'driver' => 'dropbox',
'key' => env('DROPBOX_APP_KEY'),
'secret' => env('DROPBOX_APP_SECRET'),
]
Now, when I try to run the following code, it returns false and the file doesn't appear in my Dropbox. When I change the disk to 'local', the file gets uploaded to my local storage.
$path = "pdf/file.pdf";
$storage_path = Storage::path($path);
$contents = file_get_contents($storage_path);
$upload = Storage::disk('dropbox')->put($path, $contents);
return $upload;
I've already tried clearing my config by running php artisan config:clear. After trying many different things, I have no idea what I'm doing wrong, so any advice will be appreciated!
The problem was not in the code, but in the permissions in my dropbox app: files.content.write wasn't enabled yet.
Related
I want to upload an array of files,in Laravel , and I am not sure what is the path and who to store the file. Eight now the data are stored ,but in my case the path is #. In the image below I have the data that I am sending from front (Vuejs and I am using vue-upload-component)
$fileName = [];
foreach($request->input('files') as $files){
$contractFile = new ContractFile();
$contractFile->fill([
'contract_id' => $contract->id,
'name' => $files['name'],
'path' => '#',
])->save();
}
ContractFile
class ContractFile extends Model
{
protected $fillable = ['path','contract_id','name'];
public function contract()
{
return $this->belongsTo(Contract::class);
}
}
ContractFile db
Schema::create('contract_files', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('contract_id');
$table->string('path');
$table->string('name');
$table->timestamps();
});
filesystems.php
'uploads' =>[
'driver' => 'local',
'root' => storage_path().'file/uploads',
],
You may use
foreach($request->file('files') as $uploadedFile){
$filename = time() . '_' . $uploadedFile->getClientOriginalName();
$path = $uploadedFile->store($filename, 'uploads');
$contractFile = new ContractFile();
$contractFile->contract_id = $contract->id;
$contractFile->name = $uploadedFile->getClientOriginalName();
$contractFile->path = $path;
$contractFile->save();
}
By default, the public disk uses the local driver and stores these
files in storage/app/public. To make them accessible from the web, you
should create a symbolic link from public/storage to
storage/app/public.
To create the symbolic link, you should use the storage:link Artisan command:
php artisan storage:link
In form add file input something like:
<input type="file" multiple name="attachments[]">
Then in controller action handle an array of uploaded files like:
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
// Check if there are files uploadeded for the form name attribute.
if ($request->files->has('attachments')) {
// Here we get the uploaded fileBag by attribute.
$fileBag = $request->files->get('attachments');
// Directory path where to upload the files.
$dirPath = 'attachments'
// Loop over each file in the bag to store.
foreach ($fileBag as $uploadedFile) {
// Create unique file name. You can write your logic but recommend
// using uuid to avoid name collision. Make sure to add same
// extension as uploaded file.
$fileName = (string) Str::uuid() . '.' . $uploadedFile->getClientOriginalExtension();
// Store using Storage Facades.
// Note: storing using request->file->store() will clear files array
// after first store call and since we are looping here that won't
// work.
$path = Storage::putFileAs($dirPath, $uploadedFile, $fileName);
// Now you can use the path and store it in the DB table or any way
// you want.
}
}
For more configuration refer: Laravel 7.x File Storage, Symfony File Bag, Symfony Uploaded File
I am using laravel 5.5 with backpack as admin panel and i making a project for listing Departments and their Clients and i want to use elfinder to connect to each client folder when i edit the client , So i created a middleware for elfinder to create the client folder and to change the elfinder.dir to that directory the first part of creating dir is done but the problem is in Config::set is not working ,My Code is:
The Middleware :
public function handle($request, Closure $next)
{
$iid = $request->route('client');
if (!Storage::disk('doc')->exists('$iid')){
Storage::disk('doc')->makeDirectory($iid);
}
\Config::set('elfinder.dir', $iid);
return $next($request);
}
The Route:
Route::get('admin/client/{client}/edit', 'Admin\ClientCrudController#edit')->middleware('elfindernew');
The ElfinderController :
public function showConnector()
{
$roots = $this->app->config->get('elfinder.roots', []);
if (empty($roots)) {
$dirs = (array) $this->app['config']->get('elfinder.dir', []);
foreach ($dirs as $dir) {
$roots[] = [
'driver' => 'LocalFileSystem', // driver for accessing file system (REQUIRED)
'path' => storage_path('doc')."/".$dir,
'URL' => url($dir), // URL to files (REQUIRED)
'accessControl' => $this->app->config->get('elfinder.access') // filter callback (OPTIONAL)
];
}
I don't Know what is wrong Can someone Help me.....
You have to do it like this:
config(['elfinder.dir', $iid]);
I have saved a file with this command
$newFile = [
'event_id' => $event->id,
'path' => $storePath
];
EventFile::create($newFile);
I can get the path to the file for a link like this:
Storage::disk('public')->url($file->path);
But there is no data about the file size. How can i get the file size in blade view???
Laravel 5^
$request->file('file')->getSize(); // in bytes
Laravel 4
$request->file('file')->getClientSize(); // getClientSize() is deprecated in Laravel 5
The more Simpler way is to use Storage Facade if you have already stored / uploaded file
use Illuminate\Support\Facades\Storage;
public function get_size($file_path)
{
return Storage::size($file_path);
}
Or if you are using S3 Bucket then you can modify the above function like below
use Illuminate\Support\Facades\Storage;
public function get_size($file_path)
{
return Storage::disk('s3')->size($file_path);
}
Check Laravel File Storage
getClientSize() is deprecated starting version 4.1. Use getSize() instead.
https://github.com/symfony/symfony/blob/4.1/UPGRADE-4.1.md#httpfoundation
Very simple(Proper Laravel Way):
//add this at the top of your controller
use File;
// add this with in your function
$size = File::size($PATH_OF_FILE);
laravel 8
$imageSize = $request->file('file')->getSize();
$fil->size = number_format($imageSize / 1048576,2);
$file->size My Table Change It With Your DB Table
According to the Laravel Documentation for version 8.0:
When using the local driver, all files that should be publicly accessible should be placed in the storage/app/public directory.
So the root of your local storage here is the public/ directory within storage/app/
You can Specify the method to get file size in your File Model like this
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class File extends Model
{
use HasFactory;
protected $fillable = [
'name',
'file_path'
];
public function getFileSize()
{
// Ensure $this->file_path begins with '/public/';
return Storage::size($this->file_path);
}
}
And use it like this within your blade file
<div>{{ $file->getFileSize() }}</div>
If you use it this way, $this->file_path must have the format: /public/optional_subdirectory/file_name
I'm quite new to Laravel and Lumen, so my question may be a little simple, but I couldn't find any useful answer yet.
Lumen version is 5.1.
So I tried to create a data repository supported by a cache. Firstly I want to use FileStore, then I want to move to some more appropriate.
I tried to inject Cache repository like this:
<?php
namespace App\Repositories;
use Illuminate\Cache\Repository;
class DataRepository
{
private $cache;
public function __construct(Repository $cache)
{
$this->cache = $cache;
}
}
It seemed pretty simple to me. But when I try to use this repo in my controller, and tried to inject this repo into it, during instantiation I get the following error:
BindingResolutionException in Container.php line 749:
Target [Illuminate\Contracts\Cache\Store] is not instantiable.
I guessed the repository cannot find the matching and useable store implementation. When I tried to bind the Store to \Illumante\Cache\FileStore like this:
$this->app->bind(\Illuminate\Contracts\Cache\Store::class, \Illuminate\Cache\FileStore::class);
I got a new kind of error:
Unresolvable dependency resolving [Parameter #1 [ <required> $directory ]] in class Illuminate\Cache\FileStore
I guess I have a more complicated config issue, so I didn't want to walk through the dependency tree.
In my .env I have these:
CACHE_DRIVER=file and SESSION_DRIVER=file
In Lumen I explicitly enabled the facades, the DotEnv (and the eloquent also for my data repositories).
Dotenv::load(__DIR__.'/../');
$app = new Laravel\Lumen\Application(
realpath(__DIR__.'/../')
);
$app->withFacades();
$app->withEloquent();
I tried to add a cache.php configuration. In the bootstrap/app.php I added $app->configure('cache'); to use it with the following configs:
<?php
return [
'default' => env('CACHE_DRIVER', 'file'),
'stores' => [
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache'),
],
],
];
Could you help me, how can I bootstrap the Cache properly?
Answer
The cache implementation in Lumen is registered as:
Illuminate\Contracts\Cache\Repository
Not
Illuminate\Cache\Repository
So you may change your code to:
<?php
namespace App\Repositories;
use Illuminate\Contracts\Cache\Repository;
class DataRepository
{
private $cache;
public function __construct(Repository $cache)
{
$this->cache = $cache;
}
}
P.S You don't need to configure cache, since Lumen will configure any cache configuration automatically.
Tricks
But if you still want to use Illuminate\Cache\Repository, you may bind it first in your ServiceProvider or bootstrap/app.php file:
use Illuminate\Cache\Repository as CacheImplementation;
use Illuminate\Contracts\Cache\Repository as CacheContract;
$app->singleton(CacheImplementation::class, CacheContract::class);
How to configure Kohana + Twig module so the Twig will set "writable by all" permissions on all of it's cache directory and it's descendant files?
So, for example, when I run my application through the Apache module (mod_php) and cache file owner is apache (or httpd) user, I will be able to remove cache files (to clean the cache or completely remove whole application) using regular user and ssh access.
I'm able to do it with Kohana's cache, but Twig's cache is created somehow differently.
It's not very easy, but not too complicated either. I have achieved state presented below by trial-and-error method.
Create a class that inherits from Twig_Cache_Filesystem and will be used instead of it. Check this out:
<?php
namespace Application\Twig;
class Cache_Filesystem extends \Twig_Cache_Filesystem
{
public function write($key, $content)
{
$old = umask(0000);
parent::write($key, $content);
umask($old);
}
}
Note, that this class must have it's name unique, so it is a good idea to namespace it. Also, it must be accessible to other code, so consider using composer's autoloading feature.
This is the fix itself, rest of the guide is just the way of implementing it into Kohana+Twig ecosystem.
Copy Twig.php from modules/kohana-twig/classes/Twig.php into your application's directory, i.e. application/classes/Twig.php (thank you Kohana's Cascading Filesystem!)
Modify a bit newly copied file, to let Twig_CacheInterface instance be passed in the config file (application/config/twig.php) instead of just a simple string (specifying to the Twig's cache directory). Take a look of my example:
<?php defined('SYSPATH') or die('No direct script access.');
class Twig extends Kohana_Twig
{
/**
* Initialize the Twig module
*
* #throws Kohana_Exception
* #return bool
*/
public static function init()
{
$path = Kohana::$config->load('twig.environment.cache');
if (is_string($path)) {
return parent::init();
} else if ($path instanceof Twig_CacheInterface) {
return true;
}
throw new Kohana_Exception('Twig cache could not be initialized');
}
}
In configuration file for kohana-twig module, i.e. application/config/twig.php (if not yet copied from module to your application, do it now), define environment.cache key like this:
return array(
'loader' => array(
'extension' => 'twig',
'path' => 'views',
),
'environment' => array(
'auto_reload' => (Kohana::$environment >= Kohana::TESTING),
'autoescape' => true,
'base_template_class' => 'Twig_Template',
// Following line is related to this issue and fix:
'cache' => new \Application\Twig\Cache_Filesystem(APPPATH . 'cache/twig'),
'charset' => 'utf-8',
'optimizations' => - 1,
'strict_variables' => false,
),
'functions' => array(),
'filters' => array(),
'tests' => array(),
}
This works for me. Hopefully it will help someone struggling with similar problem.