CakePHP: File replacement doesn't work - php

I'm very new on cakephp and I try to make an edit function with file replacement but it isn't working. If the file already exists I get an error message.
This is my admin_edit.ctp code:
<td>
<?php if (!empty($this->data['Stock']['filepath'])): ?>
<div class="input">
<label>Uploaded File</label>
<?php
echo $this->Form->input('filepath', array('type'=>'hidden', 'label' => false));
echo $this->Html->link(basename($this->data['Stock']['filepath']),
$this->data['Stock']['filepath']);
?>
</div>
<?php else: ?>
<?php echo $this->Form->input('filename',array('type' => 'file', 'label' => false)); ?>
<?php endif; ?>
</td>
here below stock.php validation code
public $validate = array(
'filename' => array(
// http://book.cakephp.org/2.0/en/models/data-validation.html#Validation::uploadError
'uploadError' => array(
'rule' => 'uploadError',
'message' => 'Something went wrong with the file upload - filename error',
'required' => FALSE,
'allowEmpty' => TRUE,
),
// http://book.cakephp.org/2.0/en/models/data-validation.html#Validation::mimeType
'mimeType' => array(
'rule' => array('mimeType', array('image/gif','image/png','image/jpg','image/jpeg')),
'message' => 'Invalid file, only images allowed',
'required' => FALSE,
'allowEmpty' => TRUE,
),
// custom callback to deal with the file upload
'processUpload' => array(
'rule' => 'processUpload',
'message' => 'Something went wrong processing your file - process error',
'required' => FALSE,
'allowEmpty' => TRUE,
'last' => TRUE,
)
processUpload :
public function processUpload($check=array()) {
// deal with uploaded file
if (!empty($check['filename']['tmp_name'])) {
// check file is uploaded
if (!is_uploaded_file($check['filename']['tmp_name'])) {
return FALSE;
}
// build full filename
$filename = WWW_ROOT . $this->uploadDir . DS . Inflector::slug(pathinfo($check['filename']['name'], PATHINFO_FILENAME)).'.'.pathinfo($check['filename']['name'], PATHINFO_EXTENSION);
// #todo check for duplicate filename
// try moving file
if (!move_uploaded_file($check['filename']['tmp_name'], $filename)) {
return FALSE;
// file successfully uploaded
} else {
// save the file path relative from WWW_ROOT e.g. uploads/example_filename.jpg
$this->data[$this->alias]['filepath'] = str_replace(DS, "/", str_replace(WWW_ROOT, "", $filename) );
}
}
return TRUE;
}
Error message :"Something went wrong with the file upload - filename error"
Before saving :
public function beforeSave($options = array()) {
// a file has been uploaded so grab the filepath
if (!empty($this->data[$this->alias]['filepath'])) {
$this->data[$this->alias]['filename'] = $this->data[$this->alias]['filepath'];
foreach (array_keys($this->hasAndBelongsToMany) as $model){
if(isset($this->data[$this->name][$model])){
$this->data[$model][$model] = $this->data[$this->name][$model];
unset($this->data[$this->name][$model]);
}
}
}
return parent::beforeSave($options);
Does anyone help me to find mistake ?
Thanks

Related

Uploading file in a form on codeigniter

I have tried all solutions but I can't tell what's wrong. Codeigniter keeps telling me that there's no file uploaded. I created the folder at the root of the project. I've seen other similar questions but I can't manage to make it work with their solutions.
This is my controller:
public function index() {
$this->form_validation->set_rules('name', 'name', 'required|trim|max_length[45]');
$this->form_validation->set_rules('type_id', 'type', 'required|trim|max_length[11]');
$this->form_validation->set_rules('stock', 'stock', 'required|trim|is_numeric|max_length[11]');
$this->form_validation->set_rules('price', 'price', 'required|trim|is_numeric');
$this->form_validation->set_rules('code', 'code', 'required|trim|max_length[45]');
$this->form_validation->set_rules('description', 'description', 'required|trim|max_length[45]');
$this->form_validation->set_rules('active', 'active', 'required|trim|max_length[45]');
$this->form_validation->set_rules('unit_id', 'unit', 'required|trim|max_length[45]');
$this->form_validation->set_rules('userfile', 'File', 'trim');
$this->form_validation->set_error_delimiters('<br /><span class="error">', '</span>');
if ($this->form_validation->run() == FALSE) { // validation hasn't been passed
$this->load->view('product/add_view');
} else { // passed validation proceed to post success logic
// build array for the model
$form_data = array(
'name' => set_value('name'),
'type_id' => set_value('type_id'),
'stock' => set_value('stock'),
'price' => set_value('price'),
'code' => set_value('code'),
'description' => set_value('description'),
'active' => set_value('active'),
'unit_id' => set_value('unit_id')
);
$config = array(
'upload_path' => "./uploads/",
'allowed_types' => "gif|jpg|png|jpeg",
'overwrite' => TRUE,
'max_size' => "2048000", // Can be set to particular file size , here it is 2 MB(2048 Kb)
'max_height' => "768",
'max_width' => "1024"
);
$this->load->library('upload', $config);
$this->upload->initialize($config); //Make this line must be here.
$imagen = set_value('userfile');
// run insert model to write data to db
if ($this->product_model->product_insert($form_data) == TRUE) { // the information has therefore been successfully saved in the db
if (!$this->upload->do_upload($imagen)) {
$error = array('error' => $this->upload->display_errors());
$this->load->view('product/add_view', $error);
} else {
$data = array('upload_data' => $this->upload->data());
$this->load->view('product/add_view', $data);
}
} else {
redirect('products/AddProduct', 'refresh');
// Or whatever error handling is necessary
}
}
}
This is my view (just showing the part that matters)
<?php // Change the css classes to suit your needs
$attributes = array('class' => '', 'id' => '');
echo form_open_multipart('products/AddProduct', $attributes); ?>
<p>
<label for="picture">Picture <span class="required">*</span></label>
<?php echo form_error('userfile'); ?>
<?php echo form_upload('userfile')?>
<br/>
</p>
<p>
<?php echo form_submit( 'submit', 'Submit'); ?>
</p>
<?php echo form_close(); ?>
EDIT: Applying the modification from the answer I get an error 500.
I tried to work on your code. and it worked on me after this changes
$config = array(
'upload_path' => "./uploads/",
'upload_url' => base_url()."uploads/", // base_url()."/uploads/", //added
'allowed_types' => "gif|jpg|png|jpeg",
'overwrite' => TRUE,
'max_size' => "2048000", // Can be set to particular file size , here it is 2 MB(2048 Kb)
'max_height' => "768",
'max_width' => "1024"
);
$this->load->library('upload'); //changed
$this->upload->initialize($config); //Make this line must be here.
$imagen = userfile; // $_FILES['userfile']['name'] //changed
If you get The localhost page isn’t working localhost is currently unable to handle this request. HTTP ERROR 500 possible error on your syntax, I just add 1 more } at the end of your code. You can check phpinfo() for other information. Also, there might be a problem on your file locations maybe the address you specified or the permissions if your running this on server.

PHP - Changing the file name destination when uploading photos

I am working on a web application where the user can upload photos.
I already have a PHP code where I can upload the photos to a folder in the server directory. However, the main issue I have with my code is that it keeps the original file name of the photo from before it was uploaded and after it was uploaded. My problem with that is when there are two different photos with the same file name, I'd have conflicts when they get uploaded.
Here is my code:
<?php
error_reporting(-1);
ini_set('display_errors', 'On');
require_once '_common.php';
$config = require_once '_config.php';
$fileName = '';
$mimeType = '';
$fileSize = 0;
if (empty($_FILES)) {
_error('No file received');
}
$pathArray = array();
foreach ($_FILES as $fileName => $fileData) {
if (!isset($fileData['error']) ||
is_array($fileData['error'])) {
die(json_encode(array(
'success' => false,
'status' => "Invalid Parameters.",
'files' => $_FILES
)));
}
switch ($fileData['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_NO_FILE:
die(json_encode(array(
'success' => false,
'status' => "No file sent.",
'files' => $_FILES)));
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
die(json_encode(array(
'success' => false,
'status' => "Exceeded filesize limit.",
'files' => $_FILES)));
default:
die(json_encode(array(
'success' => false,
'status' => "Unknown errors.",
'files' => $_FILES)));
}
// You should also check filesize here.
if ($fileData['size'] > 1000000) {
die(json_encode(array(
'success' => false,
'status' => "Exceeded File Size Limit.",
'files' => $_FILES)));
}
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $ext = array_search(
$finfo->file($fileData['tmp_name']),
array(
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',),
true)) {
die(json_encode(array(
'success' => false,
'status' => "Invalid file format.",
'files' => $_FILES)));
}
if (!move_uploaded_file(
$fileData['tmp_name'],
sprintf('./gallery/%s',
basename($fileData['name'])) )) {
die(json_encode(array(
'success' => false,
'status' => "Failed to move uploaded file.",
'files' => $_FILES)));
}
$uploaddir = '/gallery/';
$name = $fileData["tmp_name"];
$fullPath = sprintf('gallery/%s.%s',
basename($fileData['tmp_name']),
$ext
array_push($pathArray, $fullPath);
}
print_r(json_encode(array(
'success' => true,
'status' => "File is uploaded successfully.",
'filePath' => "$fullPath"
)));
?>
I've lost my touch in PHP, however, this is what I've tried:
if (!move_uploaded_file(
$fileData['tmp_name'],
sprintf('gallery/%s.%s',
sha1_file($_FILES['fileToUpload']['tmp_name'],
$ext)
)) {
die(json_encode(array(
'success' => false,
'status' => "Failed to move uploaded file.",
'files' => $_FILES)));
}
And should that go through, I changed $fullPath to fit the new destination I want:
$fullPath = sprintf('gallery/%s.%s',
sha1_file($_FILES['fileToUpload']['tmp_name'],
$ext);
However, none of those seemed to work.
My objective is to give the uploaded files a more or less unique file name, however, I can't seem to make sha1_file work.
I wonder if sha1_file can be made to work, or perhaps there's another way to change the destination file name in such a way I'll end up a unique file name (using date and time for example).
You could use microtime() or uniqid() functions to concatenate with your file name:
if (!move_uploaded_file(
$fileData['tmp_name'],
sprintf('gallery/%s.%s',
uniqid() . '_' . $_FILES['fileToUpload']['tmp_name'],
$ext)
)) {
die(json_encode(array(
'success' => false,
'status' => "Failed to move uploaded file.",
'files' => $_FILES)));
}
See uniqid documentation for more information about uniqid.

ExtJS4 - multi-file upload and get file path of the uploaded images after uploading

I am building an ExtJS4 web application and I have a part where I can successfully upload multiple files in a folder in my file director. I used Ivan Novakov's library to achieve this.
I created a button and in that button's handler, I had this code:
var uploadPanel = Ext.create('Ext.ux.upload.Panel', {
uploader : 'Ext.ux.upload.uploader.FormDataUploader',
uploaderOptions : {
url : 'uploadGallery.php'
},
synchronous : true
});
var uploadDialog = Ext.create('Ext.ux.upload.Dialog', {
dialogTitle : 'My Upload Dialog',
panel : uploadPanel
});
this.mon(uploadDialog, 'uploadcomplete', function(uploadPanel, manager, items, errorCount) {
console.log('manager = ' + manager);
console.log('items = ' + items);
console.log('manager result = ' + manager.result);
console.log('manager result message = ' + manager.message);
console.log('manager status = ' + manager.status);
console.log('manager filePath = ' + manager.filePath);
}, this);
uploadDialog.show();
I have my own PHP file upload handler as such:
<?php
require_once '_common.php';
$config = require_once '_config.php'; //require __DIR__ . '/_config.php';
$fileName = '';
$mimeType = '';
$fileSize = 0;
if (empty($_FILES)) {
_error('No file received');
}
$pathArray = array();
foreach ($_FILES as $fileName => $fileData) {
if (
!isset($fileData['error']) ||
is_array($fileData['error'])
) {
die(json_encode(array(
'success' => false,
'status' => "Invalid Parameters.",
'files' => $_FILES
)));
}
// Check $_FILES['fileToUpload']['error'] value.
switch ($fileData['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_NO_FILE:
die(json_encode(array(
'success' => false,
'status' => "No file sent.",
'files' => $_FILES
)));
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
die(json_encode(array(
'success' => false,
'status' => "Exceeded filesize limit.",
'files' => $_FILES
)));
default:
die(json_encode(array(
'success' => false,
'status' => "Unknown errors.",
'files' => $_FILES
)));
}
// You should also check filesize here.
if ($fileData['size'] > 1000000) {
die(json_encode(array(
'success' => false,
'status' => "Exceeded File Size Limit.",
'files' => $_FILES
)));
}
// DO NOT TRUST $_FILES['fileToUpload']['mime'] VALUE !!
// Check MIME Type by yourself.
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $ext = array_search(
$finfo->file($fileData['tmp_name']),
array(
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
),
true
)) {
die(json_encode(array(
'success' => false,
'status' => "Invalid file format.",
'files' => $_FILES
)));
}
// You should name it uniquely.
// DO NOT USE $_FILES['fileToUpload']['name'] WITHOUT ANY VALIDATION !!
// On this example, obtain safe unique name from its binary data.
if (!move_uploaded_file(
$fileData['tmp_name'],
sprintf('./gallery/%s.%s',
basename($fileData['tmp_name']),
$ext
)
)) {
die(json_encode(array(
'success' => false,
'status' => "Failed to move uploaded file.",
'files' => $_FILES
)));
}
// $uploadFile = sprintf('./gallery/%s.%s',
// sha1_file($_FILES['fileToUpload']['tmp_name']);
$uploaddir = '/gallery/';
$name = $fileData["tmp_name"];
$fullPath = sprintf('gallery/%s.%s',
basename($fileData['tmp_name']),
$ext
);
array_push($pathArray, $fullPath);
// echo '{"success": true, "status": "file Uploaded successfully", "filePath" : "$filePath"}';
// _response(true, sprintf("%s", $fullPath));
// echo(json_encode(array(
// 'success' => true,
// 'status' => "File is uploaded successfully.",
// 'filePath' => "$fullPath"
// )));
}
//_log(sprintf("[multipart] Uploaded %s, %s, %d byte(s)", $fileName, $mimeType, $fileSize));
// _response(true, $pathArray);
print_r(json_encode(array(
'success' => true,
'status' => "File is uploaded successfully.",
'filePath' => "$fullPath"
)));
?>
I didn't change much of his _common.php and _config.php which can be found here.
As you can see, at my PHP part, I am trying to send the filePath of the uploaded file back to the ExtJS part, I need this for a database entry process. However, I don't know how to obtain this JSON Object back in my ExtJS code as the function only has 4 arguments (uploadPanel, manager, items, errorCount) and so far I haven't had luck guessing which one would contain the JSON response.
I found a rather crude workaround to this issue. What I did was that I used the original filenames of the files uploaded as the filenames in the server's file system. This is NOT a good solution. If you need to save the filename to a database and the filename is a SQL Injection, then you'll have problems.
// You should name it uniquely.
// DO NOT USE $_FILES['fileToUpload']['name'] WITHOUT ANY VALIDATION !!
// On this example, obtain safe unique name from its binary data.
move_uploaded_file(
$fileData['tmp_name'],
sprintf('./gallery/%s',
basename($fileData['name'])
In this case $_FILES['fileToUpload']['name'] is $fileData['name'], check the start of my foreach loop.
As mentioned you shouldn't really use $_FILES['fileToUpload']['name'] without checking and validating it first.
This question will still be open for answers.

PHP - Getting the filepath of the file after uploading to server

Good day. I am uploading an image file to my php server. I am successfully uploading the file to a folder. What I want to do now is as I assemble my JSON response, I want to get the new file path of the file so I would know where it is programatically.
Here is my php code so far:
<?php
header('Content-Type: text/html; charset=utf-8');
if (
!isset($_FILES['fileToUpload']['error']) ||
is_array($_FILES['fileToUpload']['error'])
) {
die(json_encode(array(
'success' => false,
'status' => "Invalid Parameters. - 1",
'files' => $_FILES
)));
}
// Check $_FILES['fileToUpload']['error'] value.
switch ($_FILES['fileToUpload']['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_NO_FILE:
die(json_encode(array(
'success' => false,
'status' => "No file sent. - 2",
'files' => $_FILES
)));
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
die(json_encode(array(
'success' => false,
'status' => "Exceeded filesize limit. - 3",
'files' => $_FILES
)));
default:
die(json_encode(array(
'success' => false,
'status' => "Unknown errors. - 4",
'files' => $_FILES
)));
}
// You should also check filesize here.
if ($_FILES['fileToUpload']['size'] > 1000000) {
die(json_encode(array(
'success' => false,
'status' => "Exceeded File Size Limit. - 5",
'files' => $_FILES
)));
}
// DO NOT TRUST $_FILES['fileToUpload']['mime'] VALUE !!
// Check MIME Type by yourself.
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $ext = array_search(
$finfo->file($_FILES['fileToUpload']['tmp_name']),
array(
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
),
true
)) {
die(json_encode(array(
'success' => false,
'status' => "Invalid file format. - 6",
'files' => $_FILES
)));
}
// You should name it uniquely.
// DO NOT USE $_FILES['fileToUpload']['name'] WITHOUT ANY VALIDATION !!
// On this example, obtain safe unique name from its binary data.
if (!move_uploaded_file(
$_FILES['fileToUpload']['tmp_name'],
sprintf('./gallery/%s.%s',
sha1_file($_FILES['fileToUpload']['tmp_name']),
$ext
)
)) {
die(json_encode(array(
'success' => false,
'status' => "Failed to move uploaded file. - 7",
'files' => $_FILES
)));
}
$filePathFull = sprintf('./gallery/%s.%s',
sha1_file($_FILES['fileToUpload']['tmp_name']);
$uploaddir = '/gallery/';
$uploadfile = $uploaddir . basename($_FILES['fileToUpload']['tmp_name']);
die(json_encode(array(
'success' => true,
'status' => "File is uploaded successfully. - 8",
'files' => $_FILES,
'filePath' => $uploadfile
)));
?>
I am trying to get the new file path which is /gallery/ + the filename, however, I am getting an invalid JSON Object when I process it in my ExtJS part.
Can anyone help me with my problem? I also tried sprintf('./gallery/%s.%s', sha1_file($_FILES['fileToUpload']['tmp_name']); but that doesn't seem to work.
Any help is very much appreciated.
Edit:
So far this works:
$uploaddir = '/gallery/';
$uploadFile = $uploaddir . basename($_FILES['fileToUpload']['tmp_name']);
die(json_encode(array(
'success' => true,
'status' => "File is uploaded successfully. - 8",
'filePath' => $uploadFile
)));
However, I don't have the file extension and I get something like: /gallery/phptnLZJm but upon checking, an image is actually uploaded but the filename is off.
I made it work. I think it sha1_file was the issue. The code is now:
if (!move_uploaded_file(
$_FILES['fileToUpload']['tmp_name'],
sprintf('./gallery/%s.%s',
basename($_FILES['fileToUpload']['tmp_name']),
$ext
)
)) {
die(json_encode(array(
'success' => false,
'status' => "Failed to move uploaded file. - 7",
'files' => $_FILES
)));
}
// $uploadFile = sprintf('./gallery/%s.%s',
// sha1_file($_FILES['fileToUpload']['tmp_name']);
$uploaddir = '/gallery/';
// $uploadFile = $uploaddir . basename($_FILES['fileToUpload']['tmp_name']);
$name = $_FILES["fileToUpload"]["tmp_name"];
$fullPath = sprintf('/gallery/%s.%s',
basename($_FILES['fileToUpload']['tmp_name']),
$ext
);
die(json_encode(array(
'success' => true,
'status' => "File is uploaded successfully. - 8",
'filePath' => "$fullPath"
)));
Before, I would call sha1_file instead of basename as I am assembling my $fullPath, and I don't know why. Was it because it was moved already and now has a different name?

zf2 how to upload files, more than 1 file

I refer to http://samsonasik.wordpress.com/2012/08/31/zend-framework-2-creating-upload-form-file-validation/ and follow this, I can upload 1 file successfully by using rename filter in ZF2.
However when I use this way to upload 2 files, it goes wrong. I paste my code as following:
$this->add(array(
'name' => 'bigpicture',
'attributes' => array(
'type' => 'file'
),
'options' => array(
'label' => 'Big Pic'
)
));
$this->add(array(
'name' => 'smallpicture',
'attributes' => array(
'type' => 'file'
),
'options' => array(
'label' => 'Small Pic'
)
));
<div class="row"><?php echo $this->formRow($form->get('smallpicture')) ?></div>
<div class="row"><?php echo $this->formRow($form->get('bigpicture')) ?></div>
$data = array_merge(
$request->getPost()->toArray(),
$request->getFiles()->toArray()
);
$form->setData($data);
if ($form->isValid()) {
$product->exchangeArray($form->getData());
$picid = $this->getProductTable()->saveProduct($product);
$pathstr = $this->md5path($picid);
$this->folder('public/images/product/'.$pathstr);
//move_uploaded_file($data['smallpicture']['tmp_name'], 'public/images/product/'.$pathstr.'/'.$picid.'_small.jpg');
//move_uploaded_file($data['bigpicture']['tmp_name'], 'public/images/product/'.$pathstr.'/'.$picid.'_big.jpg');
$fileadaptersmall = new \Zend\File\Transfer\Adapter\Http();
$fileadaptersmall->addFilter('File\Rename',array(
'source' => $data['smallpicture']['tmp_name'],
'target' => 'public/images/product/'.$pathstr.'/'.$picid.'_small.jpg',
'overwrite' => true
));
$fileadaptersmall->receive();
$fileadapterbig = new \Zend\File\Transfer\Adapter\Http();
$fileadapterbig->addFilter('File\Rename',array(
'source' => $data['bigpicture']['tmp_name'],
'target' => 'public/images/product/'.$pathstr.'/'.$picid.'_big.jpg',
'overwrite' => true
));
$fileadapterbig->receive();
}
the above are form,view,action.
using this way, only the small picture uploaed successfully. the big picture goes wrong.
a warning flashed like the following:
Warning:move_uploaded_file(C:\WINDOWS\TMP\small.jpg):failed to open stream:Invalid argument in
E:\myproject\vendor\zendframework\zendframework\library\zend\file\transfer\adapter\http.php
on line 173
Warning:move_uploaded_file():Unable to move 'C:\WINDOWS\TMP\php76.tmp'
to 'C:\WINDOWS\TEMP\big.jpg' in
E:\myproject\vendor\zendframework\zendframework\library\zend\file\transfer\adapter\http.php
on line 173
Who can tell me how to upload more than 1 file in this way. you know, the rename filter way similar to above. thanks.
I ran into the same problem with a site i did. The solution was to do the renaming in the controller itself by getting all the images and then stepping through them.
if ($file->isUploaded()) {
$pInfo = pathinfo($file->getFileName());
$time = uniqid();
$newName = $pName . '-' . $type . '-' . $time . '.' . $pInfo['extension'];
$file->addFilter('Rename', array('target' => $newName));
$file->receive();
}
Hope this helps point you in the right direction.
I encountered the same problem and i managed to make it work using the below code;
$folder = 'YOUR DIR';
$adapter = new \Zend\File\Transfer\Adapter\Http();
$adapter->setDestination($folder);
foreach ($adapter->getFileInfo() as $info) {
$originalFileName = $info['name'];
if ($adapter->receive($originalFileName)) {
$newFilePath = $folder . '/' . $newFileName;
$adapter->addFilter('Rename', array('target' => $newFilePath,
'overwrite' => true));
}
}

Categories