I use the following method to get all files from a folder and my method returns some basic information about the files inside directory
public function getUploaded()
{
$files = [];
$filesInFolder = File::files(base_path() .'/'. self::UPLOAD_DIR);
foreach($filesInFolder as $path)
{
$files[] = pathinfo($path);
}
return response()->json($files, 200);
}
How would I get the size and the base name like ?
$files['name'] = ....
$files['size'] = ....
You could solve this quite neatly with a Laravel collection and SplFileInfo. Something along the following lines;
public function getUploaded()
{
$files = collect(File::files(base_path() . "/" . self::UPLOAD_DIR))->map(function ($filePath) {
$file = new \SplFileInfo($filePath);
return [
'name' => $file->getName(),
'size' => $file->getSize(),
];
});
return response()->json($files);
}
You can modify your code as follows:
foreach ($filesInFolder as $path) {
$file = pathinfo($path);
$file['size'] = File::size($path);
$file['name'] = File::name($path);
$files[] = $file;
}
Related
I'm not able to figure out what's wrong in my code.
In my project the user is allowed to upload multiple pictures for each aircraft registration number; I want to rename each uploaded files with the following rules: registration id, minus sign, progressive number; so if the user upload a new image file for the registration id xxx, the uploaded filename becomes xxx-1.jpg
The code to upload the multiple files is the following; it works fine so far...
// Count uploaded files
$countfiles = count($_FILES['files']['name']);
// Define new image name
$image = $id . '-1.jpg';
for($i=0;$i<$countfiles;$i++)
{
if(!empty($_FILES['files']['name'][$i]))
{
// Define new $_FILES array - $_FILES['file']
$_FILES['file']['name'] = $_FILES['files']['name'][$i];
$_FILES['file']['type'] = $_FILES['files']['type'][$i];
$_FILES['file']['tmp_name'] = $_FILES['files']['tmp_name'][$i];
$_FILES['file']['error'] = $_FILES['files']['error'][$i];
$_FILES['file']['size'] = $_FILES['files']['size'][$i];
// Check if the image file exist and modify name in case
$filename = $this->_file_newname($uploaddir,$image);
// Set preference
$config['upload_path'] = $upload_path;
$config['allowed_types'] = 'jpg|jpeg|png|gif';
$config['max_size'] = '5000';
$config['file_name'] = $filename;
//Load upload library
$this->load->library('upload',$config);
$arr = array('msg' => 'something went wrong', 'success' => false);
// File upload
if($this->upload->do_upload('file'))
{
$data = $this->upload->data();
}
}
}
The _file_newname() function does the file renaming jog, here you are the code:
private function _file_newname($path, $filename)
{
if ($pos = strrpos($filename, '.')) {
$name = substr($filename, 0, $pos);
$ext = substr($filename, $pos);
} else {
$name = $filename;
}
$newpath = $path.$filename;
$newname = $filename;
if(file_exists($newpath)){
$counter = 1;
if($pos = strrpos($name, '-')) {
$oldcounter = substr($name, $pos + 1);
if(is_numeric($oldcounter)){
$counter = $oldcounter++;
$name = substr($name, 0, $pos);
}
}
$newname = $name . '-' . $counter . $ext;
$newpath = $path . $newname;
while (file_exists($newpath)) {
$newname = $name .'-'. $counter . $ext;
$newpath = $path.$newname;
$counter++;
}
}
return $newname;
}
Now...the issue....the renaming function works fine if the user upload one file each time...so the first upload set the file name xxx-1.jpg, the second upload set the filename to xxx-2.jpg and so on....but....if the user upload more then one file at time...the second file become xxx-1x.jpg.
If already exists one file on server ( for example xxx-1.jpg ) and the user upload two more files..they are renamed as xxx-2.jpg ( correct) and xxx-21.jpg (wrong...should be xxx-3.jpg).
Any hint or suggestion to fix the issue?
Thanks a lot
Your new file name is out of the loop for the uploaded photos.
So it becomes static.
Put that line inside the loop:
// Define new image name
$image = $id . '-' . $i . '.jpg';
This way you are gonna keep the $id and rename the files according to the iteration of the loop - $i.
i would like to use this simple image slider for the joomgallery for my art students:
https://github.com/danielhpavey/joomgallery-slider
the only problem is the ordering. how do i get an ascending image ordering by id and not by filename ?
thanks peter
<?php
class images
{
public function __construct()
{
$file = JPATH_ROOT. '/components/com_joomgallery/interface.php';
if(!file_exists($file)){
JError::raiseError(500, 'JoomGallery seems not to be installed');
} else {
require_once $file;
$this ->interface = new JoomInterface();
}
}
public function getFirstImage()
{
$images = $this ->talkToJoomgallery();
return $images[0];
}
public function getImages()
{
$images = $this ->talkToJoomgallery();
return $images;
}
public function talkToJoomgallery()
{
$images = $this ->interface ->getPicsByCategory( $this ->categoryid );
$imagepath = $this ->joomgalleryImagePath();
$theimages = array();
$c = 0;
foreach ($images as $i){
$theimages[$c]= array(
'imgpath' => JURI::base() . $imagepath . $i->catpath . '/' . $i->imgfilename
,'imgtitle' => $i->imgtitle
,'imgtext' => $i->imgtext
);
$c ++;
}
shuffle($theimages);
return $theimages;
}
private function joomgalleryImagePath()
{
return $this ->interface ->getJConfig( 'jg_pathoriginalimages' );
}
public function __set($property, $value){
$this->$property = $value;
}
}
Your images are loaded according to image id only but this command is reindexing the array i.e shuffle($theimages);
You can comment out that line by
//shuffle($theimages)
Also for ordering images you can change this line in helper.php file
$images = $this->interface->getPicsByCategory($this->categoryid);
to
$images = $this->interface->getPicsByCategory($this->categoryid,null,'ordering' );
This will do the ordering of images the way you did drag and drop of images at the joomla administrator backend.
UPDATE AS PER YOUR LATEST QUERY
Suppose you want to add a param value (sorting) that can be controlled through admin. You ned to change the xml file mod_joomgallery_slider.xml
Just add a new field like this
<field
name = "sorting"
type = "radio"
label = "Sorting"
description = "Sort by Ordering or random"
default = "ordering"
>
<option value = "ordering">Ordering</option>
<option value = "rand()">Random</option>
</field>
Next to get the param in helper.php file then change the function talkToJoomgallery() like this
public function talkToJoomgallery()
{
//Externally calling a module param
jimport( 'joomla.html.parameter' );
jimport( 'joomla.application.module.helper' );
$module = JModuleHelper::getModule('mod_joomgallery_slider');
$moduleParams = new JRegistry();
$moduleParams->loadString($module->params);
$sorting = $moduleParams->get( 'sorting' );
$images = $this ->interface ->getPicsByCategory( $this ->categoryid,null,$sorting );
$imagepath = $this ->joomgalleryImagePath();
$theimages = array();
$c = 0;
foreach ($images as $i){
$theimages[$c]= array(
'imgpath' => JURI::base() . $imagepath . $i->catpath . '/' . $i->imgfilename
,'imgtitle' => $i->imgtitle
,'imgtext' => $i->imgtext
);
$c ++;
}
//var_dump($theimages); exit;
//shuffle($theimages);
return $theimages;
}
UPDATE: To display 2 slider modules on a single page.
Some files needs to changed:
In mod_joomgallery_slider.php file change this line at top
include('helper.php');
To
include_once('helper.php');
This ensures that the file is included once.
Another change will be to remove the function imageText in default.php and including it in helper.php class else a function redeclaration error will be thrown. But now the default.php file still give error, as function imageText will be not defined, but you already added that function to helper.php. So default.php will only work if you change
echo imageText( $i, $params );
To
echo $image->imageText( $i, $params );// You are calling helper object
Remember to change in both if and else conditions.
I am trying to store values of file paths during the Ajax upload. This is my code:
public function ajaxUpload() {
$name = "";
$path = public_path('files/uploads/articles/');
if (Input::hasFile('file')) {
$files = Input::file('file');
$filePath = [];
foreach($files as $file){
$fP = $path.$file->getClientOriginalName();
return json_encode($fP);
Image::make($file)->resize(100, 100)->save($path.'/'.$file->getClientOriginalName());
}
if (Session::has('file.Path')){
Session::push('file.Path', $fP);
Session::save();
}
else {
Session::put('file.Path', $fP);
Session::save();
}
return json_encode(Session::get('file.Path'));
}
The output of $fp in the console is:
"\/home\/vagrant\/Projects\/myProject\/public\/files\/uploads\/articles\/image_2733536a64.png"
And the error is:
LOG.error: Symfony\Component\Debug\Exception\FatalThrowableError: Fatal error: [] operator not supported for strings in /home/vagrant/Projects/myProject/vendor/laravel/framework/src/Illuminate/Session/Store.php:411
And when I try like this:
public function ajaxUpload() {
$name = "";
$path = public_path('files/uploads/articles/');
if (Input::hasFile('file')) {
$files = Input::file('file');
foreach($files as $file){
$filePath[] = $path.'/'.$file->getClientOriginalName();
Image::make($file)->resize(100, 100)->save($path.'/'.$file->getClientOriginalName());
}
Session::put('filePath', $filePath);
return json_encode($filePath);
}
return 'string';
}
Then it stores each of the paths separately and not in one array, so I only save one path in DB.
How do I list all the controllers/actions on my site? Configure::listObjects('model') doesnt seem to exist anymore. I am trying to write a function to generate/add to the ACO's in my ACL setup. Thanks.
So here is what I did. In my Resource Controller:
Include the reflection class/method libraries
use ReflectionClass;
use ReflectionMethod;
To get the controllers:
public function getControllers() {
$files = scandir('../src/Controller/');
$results = [];
$ignoreList = [
'.',
'..',
'Component',
'AppController.php',
];
foreach($files as $file){
if(!in_array($file, $ignoreList)) {
$controller = explode('.', $file)[0];
array_push($results, str_replace('Controller', '', $controller));
}
}
return $results;
}
And now for the actions:
public function getActions($controllerName) {
$className = 'App\\Controller\\'.$controllerName.'Controller';
$class = new ReflectionClass($className);
$actions = $class->getMethods(ReflectionMethod::IS_PUBLIC);
$results = [$controllerName => []];
$ignoreList = ['beforeFilter', 'afterFilter', 'initialize'];
foreach($actions as $action){
if($action->class == $className && !in_array($action->name, $ignoreList)){
array_push($results[$controllerName], $action->name);
}
}
return $results;
}
Finally, to tie them boths together:
public function getResources(){
$controllers = $this->getControllers();
$resources = [];
foreach($controllers as $controller){
$actions = $this->getActions($controller);
array_push($resources, $actions);
}
return $resources;
}
I hope that helps some people.
It doesn't look like anything similar to this is still available in Cake3, nor is it still needed because of the namespaces I think.
So in short you can try to do this:
Read all controllers from the app level controller folder
Read all plugin controller folders (Get the plugin folder via Plugin::path())
Iterate over the controllers you've collected in the previous steps (You'll need to use App::uses())
Use reflections to get the public methods from each controller
I am using CakePHP 3.x and had problems with the function "getActions"
The correct syntax for "ReflectionClass" and "ReflectionMethod" is:
public function getActions($controllerName) {
$className = 'App\\Controller\\'.$controllerName.'Controller';
$class = new \ReflectionClass($className);
$actions = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
$results = [$controllerName => []];
$ignoreList = ['beforeFilter', 'afterFilter', 'initialize'];
foreach($actions as $action){
if($action->class == $className && !in_array($action->name, $ignoreList)){
array_push($results[$controllerName], $action->name);
}
}
return $results;
}
Warning for "\" before ReflectionClass and ReflectionMethod.
Hi I want to upload a file using cake php, i got the file and i am using
move_uploaded_file() to move to a specific location but it is not moving my simple logic is
shown below
if (move_uploaded_file($this->data['Add']['upload']['tmp_name'], APP . 'views' . DS .
'static' . DS.'uploads'.DS.'Rajaram'.DS )) {
LogUtil::$logger->debug('KMP File upload Url :
'.var_export($this->data, true));
}
Thanks in Advance.
File uploading is something CakePHP doesn’t do out of the box, which is one of the only thing that annoys me about the framework.
I tackled this by adding file handling to a model using callback methods. I upload the actual file with beforeSave(), and delete the file from the file system with beforeDelete(). A sample model looks like this:
<?php
App::uses('File', 'Utility');
class Image extends AppModel {
public $name = 'Image';
public function beforeSave($options = array()) {
$fieldName = 'filename';
$field = $this->data[$this->alias][$fieldName];
if (!is_array($field)) {
$this->validationErrors[$fieldName][] = 'No file detected';
return false;
}
switch ($field['error']) {
case UPLOAD_ERR_OK:
$newFilename = time() . '.jpg';
$uploadDir = WWW_ROOT . 'files/';
$source = $field['tmp_name'];
$destination = $uploadDir . $newFilename;
if (move_uploaded_file($source, $destination)) {
$this->data[$this->alias][$fieldName] = $newFilename;
return true;
}
else {
$this->validationErrors[$fieldName][] = 'No file detected';
return false;
}
break;
default:
$this->validationErrors[$fieldName][] = 'No file detected';
return false;
break;
}
}
public function beforeDelete($cascade = true) {
$image = $this->findById($this->id);
$file = new File(WWW_ROOT . 'files/' . $image['Image']['filename']);
return $file->delete();
}
}
Obviously this isn’t a perfect implementation, so feel free to take from it, learn from it, adapt it.
This was written off-the-cuff for a project recently where there’s only one model that has images attached, but on a larger project I’d more than likely wrap it up into a nice model behavior.
In your model you can use the afterSave callback method to handle your file upload:-
public function afterSave($created) {
if (isset($_FILES['data']['name'][$this->alias]['filename'])) {
$filename = $_FILES['data']['name'][$this->alias]['filename'];
$fileInfo = pathinfo($filename);
$fileExt = isset($fileInfo['extension']) ? $fileInfo['extension'] : '';
$filename = $fileInfo['filename'];
$newFilename = "$filename.$fileExt";
$dir = WWW_ROOT . 'files' . DS . 'uploads';
$target = $dir . DS . $newFilename;
move_uploaded_file($source, $target);
}
}
You can use $newFilename to change the filename to something appropriate if need be (I tend to check if a file with the same name already exists and rename the new one to avoid overwriting it.