CakePHP3 - Upload image file - php

I am new in cakephp3. I have an Employee Table and I want to save an image path.
Below is my form in add.ctp
<?php echo $this->Form->create($employee, ['enctype' => 'multipart/form-data']); ?>
<fieldset>
<legend><?= __('Add Employee') ?></legend>
<?php
echo $this->Form->input('image_path', ['type' => 'file']);
echo $this->Form->input('first_name');
echo $this->Form->input('last_name');
echo $this->Form->input('birthday',
array(
'type' => 'date',
'label' => 'Birthday',
'dateFormat' => 'MDY',
'empty' => array(
'month' => 'Month',
'day' => 'Day',
'year' => 'Year'
),
'minYear' => date('Y')-130,
'maxYear' => date('Y'),
'options' => array('1','2')
)
);
echo $this->Form->input('address');
echo $this->Form->input('contact');
echo $this->Form->input('date_hired',
array(
'type' => 'date',
'label' => 'Date Hired',
'dateFormat' => 'MDY',
'empty' => array(
'month' => 'Month',
'day' => 'Day',
'year' => 'Year'
),
'minYear' => date('Y')-130,
'maxYear' => date('Y'),
'options' => array('1','2')
)
);
$status = array(
"employed" => "Employed",
"unemployed" => "Unemployed"
);
echo $this->Form->input('status', array('label'=>'Status', 'type'=>'select', 'options'=>$status));
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
I want to make the upload function work in my EmployeesController.php. I have tried to save it using php move_uploaded_file but it is not working. Below is the controller.
public function add()
{
$employee = $this->Employees->newEntity();
if ($this->request->is('post')) {
$employee = $this->Employees->patchEntity($employee, $this->request->data);
$employee->user_id = $this->Auth->user('id');
if ($this->Employees->save($employee)) {
$this->Flash->success(__('The employee has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The employee could not be saved. Please, try again.'));
}
if(!empty($this->data))
{
//Check if image has been uploaded
if(!empty($this->data['employees']['image_path']['name']))
{
$file = $this->data['employees']['image_path']; //put the data into a var for easy use
$ext = substr(strtolower(strrchr($file['name'], '.')), 1); //get the extension
$arr_ext = array('jpg', 'jpeg', 'gif'); //set allowed extensions
//only process if the extension is valid
if(in_array($ext, $arr_ext))
{
//do the actual uploading of the file. First arg is the tmp name, second arg is
//where we are putting it
move_uploaded_file($file['tmp_name'], WWW_ROOT . 'CakePHP/app/webroot/img/' . $file['name']);
//prepare the filename for database entry
$this->data['employees']['product_image'] = $file['name'];
}
}
//now do the save
$this->Employees->save($this->data) ;
}
}
$users = $this->Employees->Users->find('list', ['limit' => 200]);
$this->set(compact('employee', 'users'));
$this->set('_serialize', ['employee']);
}

Try this structure in your View
<?= $this -> Form -> create($employee, ['type' => 'file']) ?>
...
<?= $this -> Form -> input('image_path', ['type' => 'file', 'label' => __('Select Image')]) ?>
<?= $this -> Form -> input('first_name') ?>
...
<?= $this -> Form -> end() ?>
Controller
public function add()
{
$employee = $this->Employees->newEntity();
if ($this->request->is('post'))
{
$employee = $this->Employees->patchEntity($employee, $this->request->data);
$employee['user_id'] = $this->Auth->user('id');
//Check if image has been uploaded
if(!empty($this->data['employees']['image_path']['name']))
{
$file = $this->data['employees']['image_path']; //put the data into a var for easy use
$ext = substr(strtolower(strrchr($file['name'], '.')), 1); //get the extension
$arr_ext = array('jpg', 'jpeg', 'gif'); //set allowed extensions
//only process if the extension is valid
if(in_array($ext, $arr_ext))
{
//name image to saved in database
$employee['product_image'] = $file['name'];
$dir = WWW_ROOT . 'img' . DS; //<!-- app/webroot/img/
//do the actual uploading of the file. First arg is the tmp name, second arg is
//where we are putting it
if(!move_uploaded_file($file['tmp_name'], $dir . $file['name']))
{
$this -> Flash -> error(__('Image could not be saved. Please, try again.'));
return $this->redirect(['action' => 'index']);
}
}
}
//now do the save
if ($this->Employees->save($employee))
{
$this->Flash->success(__('The employee has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The employee could not be saved. Please, try again.'));
}
}
$users = $this->Employees->Users->find('list', ['limit' => 200]);
$this->set(compact('employee', 'users'));
$this->set('_serialize', ['employee']);
}

Related

fileUploadErrorAttack file was illegally uploaded. This could be a possible attack

I am working on multiple image uploads i got the problem that 1st image is uploading properly and for second image it shows out the file upload error attack
Can you help me to find out the problem
Controller
public function mimageAction()
{
$form = new MultipleImageForm();
$form->get('submit')->setValue('Submit');
$request = $this->getRequest();
if($request->isPost())
{
$nonFile = $request->getPost()->toArray();
$File = $this->params()->fromFiles('file');
$data = array_merge_recursive($request->getPost()->toArray(), $request->getFiles()->toArray());
//print_r($data); die;
$form->setData($data);
if ($form->isValid())
{
$count = count($data['varad']);
// $dataNew=array(
// 'test'=>trim($data['test']),
// 'file'=>trim($data['file']['name']),
// 'image'=>trim($data['image']['name'])
// );
$request = new Request();
$files = $request->getFiles();
for($i=0;$i<$count;$i++)
{
$adapter = new \Zend\File\Transfer\Adapter\Http();
$adapter->setDestination('public/img/upload/'); // Returns all known internal file information
//$adapter->addFilter('File\Rename', array('target' =>"public/img/upload" . DIRECTORY_SEPARATOR .$data['varad'][$i]['name'] , 'overwrite' => true));
$filter = new \Zend\Filter\File\RenameUpload("public/img/upload/");
$filter->filter($files['varad'][$i]['name']);
$filter->setUseUploadName(true);
$filter->filter($files['varad'][$i]['name']);
if(!$adapter->receive())
{
$messages = $adapter->getMessages();
print_r($messages);
}
else
{
echo "Image Uploaded";
}
}
// $adapter = new \Zend\File\Transfer\Adapter\Http();
// $adapter->setDestination('public/img/upload/'); // Returns all known internal file information
// $adapter->addFilter('File\Rename', array('target' =>"public/img/upload" . DIRECTORY_SEPARATOR .$image2, 'overwrite' => true));
//
// if(!$adapter->receive())
// {
// $messages = $adapter->getMessages();
// print_r($messages);
// }
// else
// {
// echo "Image Uploaded";
// }
}
}
return array('form' => $form);
}
Form
public function __construct($name = null)
{
parent::__construct('stall');
$this->setAttribute("method","post");
$this->setAttribute("enctype","multipart/form-data");
$this->add(array(
'name' => 'varad',
'attributes' => array(
'type' => 'file',
'multiple'=>'multiple',
),
'options' => array(
'label' => 'First Image',
),
'validators' => array(
'Size' => array('max' => 10*1024*1024),
)
));
$this->add(array(
'name' => 'test',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Text Box',
),
));
$this->add(array(
'name' => 'varad',
'attributes' => array(
'type' => 'file',
'multiple'=>'multiple',
),
'options' => array(
'label' => 'Second Image',
),
));
$this->add(array(
'name' => 'submit',
'type' => 'submit',
));
}
Here i also tried by getting different names for images as well as different procedures for images
I think u can't use
$request->getFiles();
for this solution.
Please try to use $adapter->getFileInfo()
It's getting files from const _FILES.
I give my example for u:
$adapter = new Zend_File_Transfer_Adapter_Http();
$newInfoData = [];
$path = $this->getBannerDirByBannerId($banner->getId());
foreach ($adapter->getFileInfo() as $key => $fileInfo) {
if (!$fileInfo['name']) {
continue;
}
if (!$adapter->isValid($key)) {
return $this->getPartialErrorResult($adapter->getErrors(), $key);
}
$fileExtension = pathinfo($fileInfo['name'], PATHINFO_EXTENSION);
$newFileName = $key . '.' . $fileExtension;
if (!is_dir($path)) {
#mkdir($path, 0755, true);
}
$adapter->addFilter('Rename', array(
'target' => $path . $newFileName,
'overwrite' => true
));
$isReceive = $adapter->receive($key);
if ($isReceive) {
$newInfoData[$key] = $newFileName;
}
}
if (!empty($newInfoData)) {
$newInfoData['id'] = $banner->getId();
return BannerModel::getInstance()->updateBanner($newInfoData);
} else {
return new Model_Result();
}

CakePHP 3: Multiple file uploading returns string instead of array

Hi I'm having a problem with multiple file uploading. Whenever I try to access the file properties it won't let me. I debugged my data and here's the output:
Instead of returning me an array, it just returns me a string under data['files']. So I'm missing properties such as 'tmp_name', 'name', etc..
My code in my .ctp file :
<?= $this->Form->create('annonce') ?>
<fieldset>
<legend><?= __('Publier une annonce') ?></legend>
<?php
echo $this->Form->input('title', ['label' => 'Titre annonce']);
echo $this->Form->input('description', ['label' => 'Description annonce', 'type' => 'textarea']);
echo $this->Form->input('price', ['label' => 'Prix ', 'type' => 'number', 'placeholder' => '0$']);
echo $this->Form->input('type_annonce', array(
'options' => array('Acheter', 'Vendre', 'Échanger', 'Autre'),
'empty' => 'Choisissez une option'), ['label' => 'Je souhaite']);
echo $this->Form->input('category', array(
'options' => array('Cheval', 'Poney', 'Matériel', 'Pension', 'Demi-pension'),
'empty' => 'Choisissez une option'), ['label' => 'Je souhaite']);
echo $this->Form->input('files.', array('type' => 'file', 'multiple' => 'true', 'enctype'=>'multipart/form-data'));
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
And my controller:
public function add()
{
debug($this->request);
$now = Time::now();
$this->log('In add annonce !', 'debug');
$annonce = $this->Annonces->newEntity();
if ($this->request->is('post')) {
if(!empty($this->request->data)) {
$this->Flash->succes(__('Annonce files not empty'));
foreach ($this->request->data['files'] as $file) {
$filename = $file['name'];
$file_tmp_name = $file['tmp_name'];
$dir = WWW_ROOT.'img'.DS.'upload';
$allowed = array('png', 'jpg', 'jpeg');
echo "<pre>"; print_r($photo); echo "</pre>";
if ( !in_array( substr( strrchr( $filename , '.') , 1 ) , $allowed) ) {
throw new InternalErrorException("Error Processing Request.", 1);
}elseif( is_uploaded_file( $file_tmp_name ) ){
move_uploaded_file($file_tmp_name, $dir.DS.Text::uuid().'-'.$filename);
}
}
}
else {
$this->Flash->error(__('Not in images'));
}
$annonce = $this->Annonces->patchEntity($annonce, $this->request->data);
$annonce->id_user = $this->request->session()->read('Auth.User.id');
$annonce->publication_date = $now;
if ($this->Annonces->save($annonce)) {
$this->log('Success saving annonce !', 'debug');
$this->Flash->success(__('The annonce has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->log($annonce->errors(), 'debug');
$this->Flash->error(__('The annonce could not be saved. Please, try again.'));
}
}
$this->set(compact('annonce'));
$this->set('_serialize', ['annonce']);
}
Try this structure.
<?= $this->Form->create($annonce, ['type' => 'file']) ?>
...
<?= $this->Form->input('files[]', ['type' => 'file', 'class' => 'file', 'multiple', 'label' => __('Select Images')]) ?>
...
<?= $this->Form->end() ?>
You need to add enctype='multipart/form-data' to the form when there are files included in it. Do it like this :
<?= $this->Form->create($annonce, ['type' => 'file']) ?>
Note - you should directly use the entity as the first parameter for the form create helper function instead of a string.

CakePHP: validation of form upload field if file exists not working

CakePHP 2.x: I am struggling with validating an image upload field in a form for adding users. The upload field is not manditory. But it validates the field always as false while the image is uploaded. It seems the whole validation is working partially. Any help would be appreciated
User.php model :
public $validate = array(
'picture' => array(
'required' => false,
'allowEmpty' => true,
'custom' => array(
'rule' => array('imageExist'),
'message' => 'There is already a picture with that name on the server'
)
));
// function to check if file already exists
public function imageExist($check) {
$picturename = $check['picture'];
$path = WWW_ROOT . 'userimages/';
$file = $path . $picturename;
if (file_exists($file)) {
return false;
} else {
return true;
}
}
add.ctp:
<?php
echo $this->Form->create('User', array('class' => 'form-horizontal', 'role' => 'form', 'div' => false, 'type' => 'file'));
echo $this->Form->input('username', array('label' => "Username"));
echo $this->Form->input('picture', array('label' => "Avatar", 'type' => 'file'));
echo $this->Form>formDefaultActions();
echo $this->Form->end();
?>
UserController.php:
public function add() {
if ($this->request->is('post')) {
$this->User->create();
// set picture and path
$filedir = WWW_ROOT . 'userimages/';
$file = $filedir . $this->request->data['User']['picture']['name'];
// upload avatar picture
move_uploaded_file(
$this->request->data['User']['picture']['tmp_name'],
$file
);
$this->request->data['User']['picture'] = $this->request->data['User']['picture']['name'];
if ($this->User->save($this->request->data)) {
$this->Session->setFlash(__('The user has been added'), 'success' );
$this->redirect(array(
'action' => 'index'
));
} else {
$this->Session->setFlash(__('The user could not be created. Please, try again'), 'error' );
}
}
}
You need to check your validation before uploading or will be always false. If you upload your file, when cakephp validates your file already exists in folder.
You can just move your logic to something like:
$this->request->data['User']['picture'] = $this->request->data['User']['picture']['name'];
if ($this->User->save($this->request->data)) {
move_uploaded_file(
$this->request->data['User']['picture']['tmp_name'],
$file
);
}
Or check, before saving:
if ($this->User->validates()) {
if ($this->User->save($this->request->data)) {
move_uploaded_file(
$this->request->data['User']['picture']['tmp_name'],
$file
);
}
}
comment this
$this->request->data['User']['picture'] = $this->request->data['User']['picture']['name'];
and also take off the 2 statements into model, required and allowEmpty.also replace in your controller:
if ($this->User->save($this->request->data))
with
if ($this->User->save($this->request->data['User']))
and the pic name should be saved into the db

CMultiFileUpload class not inserting image names on the database yii

I'm working on multi file(images) uploading functionality.
I've tried everything I got.
It's not working.
It's uploading images on the path I specified but not inserting image's names on the table column.
The table's column name is "sample"
Here's the snippet of the view:
$this->widget('CMultiFileUpload', array(
'model' => $model,
'name' => 'sample',
'attribute' => 'sample',
'accept' => 'jpeg|jpg|gif|png',
'duplicate' => 'Duplicate file!',
'denied' => 'Invalid file type',
'remove' => '[x]',
'max' => 20,
));
This is the controller's code the(the function that dealing with the part):
public function actionCreate($project_id) {
$model = new Bid();
$project = $this->loadModel('Project', $project_id);
if (count($project->bids) == 5) {
Yii::app()->user->setFlash('warning', Yii::t('bids', 'This project has already reached its maximum number of bids, so you cannot post a new bid.'));
$this->redirect(array('project/view', 'id' => $project_id));
}
if (!empty($project->bid)) {
Yii::app()->user->setFlash('warning', Yii::t('bids', 'This project has a selected bid already, so you cannot post a new bid.'));
$this->redirect(array('project/view', 'id' => $project_id));
}
if ($project->closed) {
Yii::app()->user->setFlash('warning', Yii::t('bids', 'You cannot add bids as this project has been closed.'));
$this->redirect(array('project/view', 'id' => $project_id));
}
$model->project = $project;
if (isset($_POST['Bid'])) {
$model->attributes = $_POST['Bid'];
$photos = CUploadedFile::getInstancesByName('sample');
if (isset($photos) && count($photos) > 0) {
foreach ($photos as $image => $pic) {
$pic->name;
if ($pic->saveAs(Yii::getPathOfAlias('webroot').'/images/'.$pic->name)) {
// add it to the main model now
$img_add = new Bid();
$img_add->filename = $pic->name;
$img_add->save();
}
else {
}
}
}
$model->project_id = $project->id;
$model->freelancer_id = $this->currentUser->id;
if ($model->save()) {
$this->redirect(array('project/view', 'id' => $project->id, '#' => 'bidslist'));
}
}
$this->render('create', array(
'model' => $model,
));
}
Thanks in Advance.
Please let me know if anyone needs anything else for better understanding.
If i underssot you correctly when you saving the model
$img_add = new Bid();
$img_add->sample = $pic->name;
$img_add->save();

cakephp, save multiple row of the same model

I'm tying to figure out how to save, for example 4 days of schedule in one view, and have each field validation message show if validation fails.
My approach was at first to use $this->SomeModel->saveAll() but couldn't save so I tried another way using foreach and all data is saved (pass validation) but no validation message is shown. if you guys know better way to do this I'm open for any suggestions.
Model
public $validate = array(
'hour_from'=>array(
'some mgs' => array(
'rule' => 'good_hours',
),
),
);
public function good_hours($data) {
//throw new Exception(($data['hour_from'] >= $this->data['Hour']['hour_to']));
if ($data['hour_from'] >= $this->data['Hour']['hour_to']) {
return false;
}
return true;
}
Controller:
if ($this->request->is('post')) {
$all_good = true;
foreach ($this->request->data['Hour'] as $day){
if ($this->Hour->save($day)){
}else {
$all_good = false;
$this->Session->setFlash('hours not saved');
}
}
//if all saves are correct rediredt to index
if ($all_good) {
$this->Session->setFlash(__('Hours saved'));
return $this->redirect(array('action' => 'index'));
}
}
View
foreach ($days as $count => $day):
$form_model ='Hour.'.$count. '.';
?>
<fieldset>
<legend><?php
$day_array = (array) $day;
$day = $day_array['date'];
echo $day;
?></legend>
<?php
echo $this->Form->input($form_model.'type_holiday_id', array(
'label'=> 'Typ urlopu',
'type' => 'select',
'options' => $type_holidays,
'empty' => true
));
echo $this->Form->input($form_model.'hour_from', array('label' => 'od'));
echo $this->Form->input($form_model.'hour_to', array('label' => 'do'));
echo $this->Form->input($form_model.'date', array('type' => 'hidden', 'value' => $day));
echo $this->Form->input($form_model.'subordinate_id', array('type' => 'hidden', 'value' => $user['User']['id']));
echo $this->Form->input($form_model.'supervisor_id', array('type' => 'hidden', 'value' => $current_user['id']));
?>
</fieldset>
Request->data array
Hour(array)
0(array)
type_holiday_id
hour_from 8
hour_to 15
date 2014-01-20
subordinate_id 193
supervisor_id 557
1(array)
type_holiday_id
hour_from 7
hour_to 14
date 2014-01-21
subordinate_id 193
supervisor_id 557
Ok i found solution, and everything works perfectly now in controller i needed to change save to saveAll, function add in Controller should look like this:
if ($this->request->is('post')) {
if ($this->Hour->saveAll($this->request->data['Hour'], Array('validate' => 'first', 'deep' => true))){ <--- most important is that data['Hour']
$this->Session->setFlash(__('Godziny robocze zapisane'));
return $this->redirect(array('action' => 'index'));
} else{
$this->Session->setFlash('Godziny robocze nie zostały zapisane.');
}
}

Categories