friendsofcake / cakephp-upload Goto Github PK
View Code? Open in Web Editor NEWCakePHP: Handle file uploading sans ridiculous automagic
Home Page: https://cakephp-upload.readthedocs.io/
License: MIT License
CakePHP: Handle file uploading sans ridiculous automagic
Home Page: https://cakephp-upload.readthedocs.io/
License: MIT License
Can I set thumbnailQuality when using GD?
P.s. thanks! apart from the above problem, this is the first upload plugin that i got working :)
I'm using MAMP Version 2.0.5 for local development and CakePHP 2.1.3, on Mac OSX.
Similar to #53 I don't see any uploaded files,
or error messages. So, the "photo_dir" entry is empty.
I added the entries "photo" and "photo_dir" to my existing table and followed all instructions, but
different from your description I didn't use "echo $this->Form->create('User', array('type' => 'file'));"
but "echo $this->Form->create('User');", because with it, it doesn't work. Is it necessary to work?
I also didn't create an Attachment model, as I didn't need that option.
What am I doing wrong?
Regards.
There are currently several places in the plugin that use various naming schemes to get the correct path of an uploaded file or an image thumbnail:
thumbnailName
depends upon the value of thumbnailPrefixStyle
when thumbnailName
is null.thumbnailPath
defaults to path
_setupField()
_resizeImagick()
_resizePhp()
_prepareFilesForDeletion()
afterSave()
We also have _path()
method which derives paths for file uploading, but sometimes can't be used because it does too much replacement.
The other issue is that sometimes users would like to override the naming setup such that they can name things in a logical order.
Ideally there would be a single method for each, retrievePath()
, retrieveName()
, which would take the following options:
$model
$field
$data
(whether from the current save or retrieved from the db)$options
array
isThumbnail
- a boolean field that is on when we are trying to infer a thumbnail pathbasePath
- something like {ROOT}webroot{DS}files{DS}{size}{DS}{field}{DS}
rootDir
- root directory to replace {ROOT}
geometry
size
thumbnailType
thumbnailName
thumbnailMethod
mediaThumbnailType
dir
field namesaveType
- create
, update
, delete
With these changes, we could have the user write an override method that would return the data as needed. This would obviate the need for #2 to some extent, as well as create a potential need for #3.
The other thing would be to allow an afterSave()
callback to rename the original images if necessary - in the case of a created record, we would need to rename the original file if we are to properly handle #2.
Unfortunately, given that we would allow a user to override these methods, its important to provide a very good general case. It wouldn't necessarily complete #2, but the request in #2 is definitely outside of the scope of this plugin, but easily achievable through a callback.
Would be nice to provide a Set-based naming implementation, wherein the user could specify something like {Post.group_id}
and it would be used as a replacement in either the name or the path. The following regular expression will be useful in such an endeavor: \{[\w\.]+\}
Should close both #2 and #3 when this ticket is completed. Will obviously be a fair amount of work, but will ultimately make the plugin a bit more dry as well as give developers the flexibility they need on the filesystem for storing uploaded files.
Cake v : 2.0.5
validation rule:
'img' => array(
"valid ext" => array(
'rule' => array('isValidExtension', array('jpg', 'png', 'tif'), false),
'message' => 'File upload directory does not exist'
)
)
file field:
echo $this->Form->file("Event.img", array("label"=>false,"div"=>false))
When a user uploads a file with an extension not in the array it doesn't render an error next to the file field in the view.
it however does blocks the upload.
save image from clipboard (Ctrl^C) and create resizes ... From-Clipboard button next to browse-button
I am following the instructions for a basic upload (no thumbnails) and nothing is being uploaded. I am using Apache 2.2, Win XP.
I've made the database table, copy-pasted everything from the example. There's no error, no warning, nothing in logs. Cake says my record was saved. And in the database all is well. The file name and path fields have the right info. But within htdoc/app/webroot/files nothing is saved. For that matter I can't find them anywhere in the entire Apache directory.
What am I doing wrong?
Cheers,
syg
Notice (8): Undefined index: User [APP/Plugin/Upload/Model/Behavior/UploadBehavior.php, line 329]
Warning (2): Invalid argument supplied for foreach() [APP/Plugin/Upload/Model/Behavior/UploadBehavior.php, line 329]
I get these errors when deleting a record without any uploads stored on the server which for me is a common occurrence.
Haven't had time to work through the code, but rigged it by basically checking for an empty array before calling unlink like below:
public function afterDelete(&$model) {
$result = array();
if(!empty($this->__filesToRemove[$model->alias])){ // Added to fix warnings on delete w/o upload
foreach ($this->__filesToRemove[$model->alias] as $file) {
$result[] = $this->unlink($file);
}
} // added this too
return $result;
}
Do you see any issues with this method? Am I missing something that causes the error in the first place?
When uploading an image the Image.name field is not saving to the database
This occurs with a hasOne relationship to the Image file
When I was using a hasMany relationship I was getting an simular error with the file/image not being uploaded but the database field name being saved
code - http://bin.cakephp.org/saved/78304
a debug on the beforeSave inside the uploadBehavior reveals
// /app/Plugin/Upload/Model/Behavior/UploadBehavior.php (line 208)
array(
'Image' => array(
'foreign_key' => '50508b1d-ab44-4bde-a101-90ddcf5aad84',
'image' => array(
'name' => 'TTCOL.jpeg',
'type' => 'image/jpeg',
'tmp_name' => '/private/var/tmp/phpS6lOcc',
'error' => (int) 0,
'size' => (int) 298578
)
)
)
which shows the name field
tested on cake 2.3
Basically, if I upload an image and have three thumb sizes specified: small, medium, and large - I would like to have subfolders called small, medium, and large respectively.
Line 750 should be
'{model}' => $model->alias,
insted of
'{model}' => Inflector::underscore($model->alias),
save file info like file size / dimensions / mime type / file type
Hi there,
I'm using configuration below:
public $actsAs = array(
'Upload.Upload' => array(
'nome' => array(
'pathMethod' => 'flat',
'path' => '{ROOT}webroot{DS}files{DS}{model}{DS}{field}{DS}',
'fields' => array('dir' => 'caminho', 'type' => 'tipo', 'size' => 'tamanho'),
'extensions' => array('.txt','.pdf','.doc','.xls','.odt','.xml'),
)
)
);
echo $this->Form->input('operadora_id');
echo $this->Form->input('descricao');
echo $this->Form->input('nome', array('type'=>'file'));
echo $this->Form->input('caminho', array('type'=>'hidden'));
Files have been copied to the folder. But field 'caminho' isn't saving full path. He remains blank.
Greetings,
I'm using FLAT system, so all the files are uploaded to webroot/files/{Model}.
When I upload 2 records with images which have same image name, the first image is overwritten by second one.
If I delete one record, the image is also deleted, so the other record doesn't link properly anymore to it.
Basically, I would like to have this folder structure for example:
(User model with avatar_picture and signature_picture)
webroot/files/User/{Record_ID}_avatar_picture.png
webroot/files/User/{Record_ID}_signature_picture.png
Is it possible to custom set filename? At least to have a value of time(), so that no accident overwriting accures.
One more thing, when i use FLAT system, it still asks me for directory path (when editing, deleting), but the path will always be empty string.
I'm sorry if I missed the section for asking all of those, this is my first post on github, I made account because of this wondefull plugin. You did great job doing it.
Cheers
This is a feature request to aid application testing.
I am building tests to prove a model can successfully upload a file using the Upload plugin using https://github.com/davidpersson/media/blob/next/tests/fixtures/test_data.php from the Media plugin to generate the actual upload files on the fly.
The uploads will always fail when testing because handleUploadedFile() correctly uses 'is_uploaded_file()' as a check that the file came via the HTTP POST system. When testing this is not the case, so I would like to propose some sort of config variable or constant which can be used to tell handleUploadedFile() to use rename() instead of is_uploaded_file().
At the moment I am using https://gist.github.com/1501299 as my way of doing it.
Would be nice to allow absolute paths (can be if the path starts with / but that might not work well on winderz). Symlink isn't really an answer for my case because the file should not be accessible directly.
The _getPathRandom method will return same paths for upload requests of same fields, that are issued in the same second. Shouldn't there be a more sofisticated random path?
Hi Jose, here are some features which make the upload even cooler :
Regards,
Frank
[email protected]
Hello,
thank you for this nice plugin!
Here is my problem:
I have a model 'Answer' and this model has a property 'image'. When I try to create a new dataset of Answer, nothing is uploaded.
After this, when I update the same dataset, the image is upoaded properly and erverything works.
So to upload one image I have to oben the form two times.
How can I fix this problem?
Thumbnails are given name "mythumbnail." when no thumbnail extension is specified
Some more documentation.
Sometimes you may wish to provide a checkbox to indicate that a file should be deleted. This checkbox should be defined like this:
<?php
// app/View/Companies/edit.ctp
echo $this->Form->checkbox('Company.logo.remove', array('hiddenField' => false));
?>
where 'Company' is the name of the model, and 'logo' is the name of the field.
If, in beforeSave()
in the behavior, this line:
$removing = isset($model->data[$model->alias][$field]['remove']);
is changed to this:
$removing = !empty($model->data[$model->alias][$field]['remove']);
the hidden field in the form no longer needs to be suppressed.
Cheers,
Rob
Hi, I try to use upload plugin with validation (isWritable). In development server all work, but in production this validation fail everytimes.
I see isWritable() code for search bug and i see that is_writable() php function have argument with non absolute path.
var_dump(is_writable($this->settings[$model->alias][$field]['path']), is_writable(*APP.*$this->settings[$model->alias][$field]['path']));
return: bool(false) bool(true)
return is_writable(ROOT . DS . APP_DIR . DS .$this->settings[$model->alias][$field]['path']);
fix this problem.
PS: prepend ROOT.DS.APP_DIR.DS to isValidDir() too.
Hi,
I tried to add some data validation as shown in the documentation, but it doesn't seems work. I think I did it wrong so I need some help.
For isValidExtension, I suppose I must change the parameters but how do I do? How do I know which parameters?
Thanks in advance for your reply.
It is changing the extension of uploaded .jpg files to .JPEG - and it throws errors that it cannot find the file specified.
Thumbs created with PHP method don't have alpha channel
Save original file name in own table field "original_filename" ... so to have a reference
Is there a way to set only width or height for a thumbnail size?
For example if I don't care about the resulting height of a thumbnail, but I need it to be a specific width.
I'm arranging pictures with different heights in three columns to get a nice visual effect. I used another php uploader and thumb-generator for that but it was not related to cakephp in any way, and I really like this uploader plugin, so it'd be awesome if there was a way.
Thanks in advance!
I just installed the Upload plugin into my CakePHP application and couldn't get it to actually move uploaded files. I removed the @ from move_uploaded_file() in UploadBehavior::handleUploadedFile() and found that the behavior was trying to move the uploaded file into the directory "C:\xampp\htdocs\data_center\app_projects\C:\xampp\htdocs\data_center\app_projects\webroot\files\graphic\image\18\07_cover.jpg".
Digging deeper, it appears that in UploadBehavior::_path(), the preg_match() function was acting as if it couldn't find the C:\ at the start of the path string, i.e.
preg_match('/^([a-zA-Z]:\\|\\\\)/', $newPath)
was returning 0 if
$newLine = 'C:\xampp\htdocs\data_center\app_projects\webroot\files\graphic\image\\';
I'm not great at working with regular expressions, but I played around with this for a bit and got preg_match() to return 1 and the plugin to work as expected when the regex is defined as '/^([a-zA-Z]:\\\|\\\\\\\\)/'
instead.
Would this be attributable to a quirk on my system or should the regex in the plugin be updated?
Thumbnail functionality should be extracted from this plugin and created as a plugin that compliments this plugin.
The usage of finfo makes the requirement of the upload plugin restricted to PHP > 5.3
I'm not against the 5.3.x requirement but it does cause a failure in _prepareFilesForDeletion
So the requirements should either be upgraded of maybe look for a fall back method of this. Thoughts?
function _getMimeType($filePath) {
$finfo = new finfo(FILEINFO_MIME_TYPE);
return $finfo->file($filePath);
}
upload movie files and make thumbnails with n frames from beginning (sometimes beginning is just black so it makes sense to capture thumbnail image a bit later in the movie
There seems to be a windows path issue?
The images are not uploading and I am receiving the following error.
Warning (2): copy(C:\xampp\htdocs\bigdojo\app\C:\xampp\htdocs\bigdojo\app\webroot\files\user\photo\1039\Hydrangeas.jpg) [function.copy]: failed to open stream: Invalid argument [APP\plugins\upload\models\behaviors\upload.php, line 944]
Warning (2): imagecreatefromjpeg(C:\xampp\htdocs\bigdojo\app\C:\xampp\htdocs\bigdojo\app\webroot\files\user\photo\1039\xvga_Hydrangeas.jpg) [function.imagecreatefromjpeg]: failed to open stream: Invalid argument [APP\plugins\upload\models\behaviors\upload.php, line 978]
Warning (2): imagecreatefromjpeg(C:\xampp\htdocs\bigdojo\app\C:\xampp\htdocs\bigdojo\app\webroot\files\user\photo\1039\vga_Hydrangeas.jpg) [function.imagecreatefromjpeg]: failed to open stream: Invalid argument [APP\plugins\upload\models\behaviors\upload.php, line 978]
Warning (2): imagecreatefromjpeg(C:\xampp\htdocs\bigdojo\app\C:\xampp\htdocs\bigdojo\app\webroot\files\user\photo\1039\thumb_Hydrangeas.jpg) [function.imagecreatefromjpeg]: failed to open stream: Invalid argument [APP\plugins\upload\models\behaviors\upload.php, line 978]
I get the error in line 1191 (upload.php) to set deleteOnUpdate
Call to undefined function mime_content_type().
I set up temporarily to return empty string to make it work.
Cakephp 2.0, PHP 5.3+
In Strict mode, PHP gives this message for all validation rules: "Only variables should be passed by reference" (PHP 5.4.3); it is triggered by the lines
$field = array_pop(array_keys($check));
If those lines are changed to this, the error disappears:
$field_keys = array_keys($check);
$field = array_pop($field_keys);
[100ร80] should maintain the aspect ratio and it doesn't.
If a file fails to upload, the "moveUploadedFile" rule is invalidated but because there isn't a moveUploadedFile function defined, cake assumes the rule must be a regex and throws a warning:
Warning: Warning (2): preg_match() expects parameter 2 to be string, array given in [cake\libs\model\model.php, line 2611]
Adding a stub moveUploadedFile custom rule should fix the problem and allow for custom messages when this error occurs.
Hi, as from email i'm here opening a ticket.
When i upload a file there are no problems, but If i edit the image (replacing with another) or delete it the work is done but i get informations as you can see in the following gist:
https://gist.github.com/2119898
following the gist to my model:
https://gist.github.com/2120149
my installation is as follows:
Apache version 2.2.21
PHP version 5.2.17
MySQL version 5.1.61
Architecture i686
Operating system linux
Kernel version 2.6.18
UPDATE:
migrated on new server (same hosting) now PHP version is 5.3.2 and Kernel is 2.6.32, the rest is the same as before.
An excellent feature of the Media Plugin was the ability to recreate thumbnails via the console. This is especially helpful when you need to create a new thumbnail size on an existing application; which in the perfect world wouldn't happen, but can be necessary due to visual design changes etc.
Currently I am unaware of any way to do this without having to add the new sizes and then reupload the image.
An alternative would be perhaps an "Update thumbnails?" form check box, which, if ticked, would locate the original source image and regenerate the [new] thumbs.
I might be missing something in the plugin that offers a way to achieve this.
Hi
Sorry in advance if this is a stupid question but I'm kinda new in CakePHP
I need some help to display the image that i uploaded
Can someone help me please :))
Thanks in advance
With more than one file, hitting UploadBehavior::save()
with this $model->data
:
Array(
[Image] => Array(
[0] => Array(
[filename] => Array(
[name] => Family-Guy.jpg
[type] => image/jpeg
[tmp_name] => /tmp/php3lEg2Q
[error] => 0
[size] => 56044
)
)
[1] => Array(
[filename] => Array(
[name] => Homer_Simpson.jpg
[type] => image/jpeg
[tmp_name] => /tmp/phpC2tDtp
[error] => 0
[size] => 26379
)
)
)
)
Results in the line:
if (!isset($model->data[$model->alias][$field])) continue;
failing, which means the remaining of UploadBehavior::save()
is not executed and nothing is inserted in db.
Hello,
I have setted up your plugin and it works correctly just for one thing: in UploadBehavior I have specified the path directory to upload the files but it always uploads creating a directory into this one, why ??
Thanks
-A
Hello! I have an error:
Error: Call to undefined function mime_content_type()
File: C:\wamp\www\libreria\plugins\Upload\Model\Behavior\UploadBehavior.php
Line: 1196
This error appears when i try to delete an element of the database, im using wamp, php 5.4.3, cake 2.2 and Upload Plugin 2.0.
Some idea please? Thank you!
I have changed beforeSave to delete current file when saving a new one.
function beforeSave(&$model) {
foreach ($this->settings[$model->alias] as $field => $options) {
if (!is_array($model->data[$model->alias][$field])) continue;
if (!empty($model->data[$model->alias][$field]['remove']) || !empty($model->data[$model->alias][$model->primaryKey])) {
//if the record is already saved in the database, set the existing file to be removed after the save is sucessfull
$data = $model->find('first', array(
'conditions' => array("{$model->alias}.{$model->primaryKey}" => $model->id),
'contain' => false,
'recursive' => -1,
));
$this->_prepareFilesForDeletion($model, $field, $data, $options);
if (!empty($model->data[$model->alias][$field]['remove'])) {
$model->data[$model->alias][$field] = null;
}
} elseif (empty($model->data[$model->alias][$field]['name'])) {
// if field is empty, don't delete/nullify existing file
unset($model->data[$model->alias][$field]);
continue;
}
$this->runtime[$model->alias][$field] = $model->data[$model->alias][$field];
$model->data[$model->alias] = array_merge($model->data[$model->alias], array(
$field => $this->runtime[$model->alias][$field]['name'],
$options['fields']['type'] => $this->runtime[$model->alias][$field]['type'],
$options['fields']['size'] => $this->runtime[$model->alias][$field]['size']
));
}
return true;
}
As PHP determines the file type from the file content, and the web server may determine the file type by the file extension, it's always safer to store files outside the DocumentRoot and have them served through PHP, instead of linking directly to the files.
If the Upload behavior had an afterFind() callback like this:
<?php
// app/Plugin/Upload/Model/Behavior/UploadBehavior.php
public function afterFind(Model $model, $results, $primary) {
foreach ($results as $rkey => $rval) {
foreach ($this->settings[$model->alias] as $skey => $sval) {
if (array_key_exists($model->alias, $rval) && array_key_exists($skey, $rval[$model->alias])) {
$results[$rkey][$model->alias][$skey . '_path'] = $this->settings[$model->alias][$skey]['path'] . $this->_getPath($model, $skey) . DIRECTORY_SEPARATOR;
}
}
}
return $results;
}
?>
I could have a controller method like this:
<?php
// app/Controller/CompaniesController.php
public function logo($id = null) {
$this->Company->id = $id;
$company = $this->Company->find('first', array(
'fields' => array(
'logo',
),
'conditions' => array(
'Company.id' => $id,
'NOT' => array(
'Company.logo' => null,
),
),
'recursive' => -1,
));
$this->viewClass = 'Media';
if ($company) {
$params = array(
'id' => $company['Company']['logo'],
'path' => $company['Company']['logo_path'],
'download' => false,
);
}
else {
// Fallback.
$params = array(
'id' => 'nologo.png',
'path' => 'img/',
'download' => false,
);
}
$this->set($params);
}
?>
And to display the company logo in a view, I would only need to do this:
<?php
// app/View/Companies/view.ctp
echo $this->Html->image(array('controller' => 'companies', 'action' => 'logo', $company['Company']['id']), array('alt' => $company['Company']['name']));
?>
Obviously, this could be extended to other file types as well.
Feel free to use this code and documentation.
Cheers,
Rob
I started using the upload plugin since a couple of weeks, and noticed (correct me if I am wrong) that there is no easy way to generate URLs pointing to uploaded files.
By default, uploaded files get copied inside WEBROOT/files/MODEL/FIELD/ID/UPLOADEDNAME
, and in the database only the filename is saved in the record. How are applications supposed to create an URL pointing to the uploaded file? Hard-coding the URL creation does not seem to me the right solution. Please, shed some light on the topic.
Regards,
Matteo
I noticed that if the valid extensions array is array('jpg')
, then the extensions .Jpg and .JPG don't pass. Since I can't think of a good reason not to allow case-variations of valid extensions, I modified line 689 from this
return in_array($pathInfo['extension'], $extensions);
to this
return in_array(strtolower($pathInfo['extension']), $extensions);
And immediately before that line, to allow for the array of valid extensions to be written in either upper or lower case,
$extensions = array_map('strtolower', $extensions);
There's probably a more elegant way to do case-insensitive extension validation, but this is what I came up with.
Create Thumbnail with logic based on Aspect Ratio (x/y = AR), where befor AR-Breakpoint the image is sized x=n (config) and y=n_AR and when reaching the breakpoint it is y=n and x=n_AR ... this leads to balanced thumbnail creation where no thumbnails get too long or to high
Hello,
Why some of the validation rules return false with no file uploaded ?
"Non-file uploads also mean the mimetype is invalid"
I agree, but how to make a not required file field ?
I had to edit the Upload Behavior to return true when no file is uploaded.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.