I'm trying to create a new folder within the upload folder so that a user can upload file to there own folder.
Can I do this using PHP or do I need to a column "LONGBLOB" in MYSQL?
I've read that it's not good practice to store images in you database
<?php
header('Content-Type: application/json');
$succeeded = [];
$failed =[];
$uploaded = [];
$allowed = ['png', 'gif', 'jpg'];
if(!empty($_FILES["file"])) {
foreach ($_FILES['file']['name'] as $key => $name) {
if ($_FILES['file']['error'][$key] === 0) {
$temp = $_FILES['file']['tmp_name'][$key];
$ext = explode('.', $name);
$ext = strtolower(end($ext));
$file = md5_file($temp) . time() . '.' . $ext;
if (in_array($ext, $allowed) === true && move_uploaded_file($temp, "uploads/{$file}") === true) {
$succeeded[] = array(
'name' => $name,
'file' => $file
);
}else{
$failed[] = array(
'name' => $name);
}
}
}
}
if (!empty($_POST['ajax'])) {
echo json_encode(array(
'succeeded' => $succeeded,
'failed' => $failed ));
}
?>
Assuming you have the user's username or id in a session variable then that could be used as the basis for the new folder into which he/she would upload files.
Obiously that same username,id would have to be used when they wish to download the file. By storing a hash and the filepath you can generate links that do not reveal filename, folder path, owner etc as the db could check the ash and return the file and path when needed.
The following is an untested example of generating the user's own folder and using that in the upload process - hope it gives you some ideas / guidance.
<?php
$succeeded = [];
$failed =[];
$uploaded = [];
$allowed = ['png', 'gif', 'jpg'];
/*
generate a suitable name for the new folder,
remove characters which might be troublesome
*/
$userdir = str_replace(
array("'",'"','-'),
array('','','_'),
$_SESSION['username']
);
/*
new path into which the files are saved
It might be better to have the files
stored outside of the document root.
*/
$savepath = 'uploads/' . $userdir;
/* create the folder if it does not exist */
if( !file_exists( $savepath ) ) {
mkdir( $savepath );
chown( $savepath, $username );
chmod( $savepath, 0644 );
}
if( !empty( $_FILES["file"] ) ) {
foreach( $_FILES['file']['name'] as $key => $name ) {
if( $_FILES['file']['error'][$key] === 0 ) {
$temp = $_FILES['file']['tmp_name'][$key];
/*
is there anything to be gained by hashing the filename?
the hash would be the same for filenames with the same
name anyway.
If the file is large, calculating the hash of the file could
take some time...
*/
$ext = explode('.', $name);
$ext = strtolower( end( $ext ) );
$file = md5_file( $temp ) . time() . '.' . $ext;
/* generate a random hash to use in downloads */
$hash=uniqid( md5( date(DATE_COOKIE) ) );
/* here probably - store reference in db? Assign permissions based upon owner etc */
$sql='insert into `table` (`filename`,`username`,`uid`,`datetime`,`hash`) values (?,?,?,?,?);';
/* bind params and execute - not shown */
if ( in_array( $ext, $allowed ) === true && move_uploaded_file( $temp, "{$savepath}/{$file}") === true ) {
$succeeded[] = array( 'name' => $name, 'file' => $file );
}else{
$failed[] = array( 'name' => $name );
}
}
}
}
if (!empty($_POST['ajax'])) {
header('Content-Type: application/json');
echo json_encode(array(
'succeeded' => $succeeded,
'failed' => $failed ));
} else {
header( 'HTTP/1.1 404 Not Found', true, 404 );
}
?>
Related
When I update the database, it uploads a single image. How do I upload multiple?
$id = $this->request->getPost('id');
$model = new UrunModel();
$file = $this->request->getFile('resim');
$resim_eski = $model->find($id);
if($file->isValid() && !$file->hasMoved()){
$eski_resim = $resim_eski['resim'];
if(file_exists("dosyalar/uploads".$eski_resim)){
unlink("dosyalar/uploads".$eski_resim);
}
$imagename = $file->getRandomName();
$file->move("dosyalar/uploads", $imagename);
}else{
$imagename = $resim_eski['resim'];
}
if ($this->request->getFileMultiple('images')) {
foreach($this->request->getFileMultiple('images') as $res)
{
$res->move(WRITEPATH . 'dosyalar/uploads');
$data=[
'baslik' => $this->request->getPost('baslik'),
'slug' => mb_url_title($this->request->getPost('baslik'), '-', TRUE),
'kisa_aciklama' => $this->request->getPost('kisa_aciklama'),
'kategori' => $this->request->getPost('kategori'),
'query_kategori' => $this->request->getPost('query_kategori'),
'aciklama' => $this->request->getPost('aciklama'),
'fiyat' => $this->request->getPost('fiyat'),
'indirimli_fiyat' => $this->request->getPost('indirimli_fiyat'),
'resim' => $imagename,
'resimler' => $res->getClientName(),
'type' => $res->getClientMimeType()
];
$model -> update($id,$data);
}
}
return redirect()->to(base_url('yonetim/urunler'));
}
Controller code above, I've been struggling for 2 days, I couldn't manage it somehow.
When I run the code, it just adds 1 image to each product. I want to add more than one image to 1 product for the gallery part. Any suggestions for this code or a different solution?
function add()
{
$length = count($_FILES['image']['name']);
$filename = $_FILES['image']['name'];
$tempname = $_FILES['image']['tmp_name'];
$allimage = array();
foreach($filename as $key =>$value)
{
move_uploaded_file($tempname[$key],'media/uploads/mobile_product/'.$filename[$key]);
$allimage[] = $filename[$key];
}
if(!empty($allimage))
{
$allimage = json_encode($allimage);
}
else
{
$allimage = '';
}
$data['image'] = $allimage;
$this->db->insert('table',$data);
}
CI4 Controller:
if($this->request->getFileMultiple('image_files')) {
$files = $this->request->getFileMultiple('image_files');
foreach ($files as $file) {
if ($file->isValid() && ! $file->hasMoved())
{
$newNames = $file->getRandomName();
$imageFiles = array(
'filename' => $newNames
);
$modelName->insert($imageFiles );
$file->move('uploads/', $newNames);
}
}
}
HTML
<input type="file" name="image_files[]">
This is the shortest way to do that
I want to upload multiple image using PDO in one row with comma separation, however I can only able to insert one image to database but in the upload directory all selected files are moved. How to do it?
<?php
for($x=0; $x<count($_FILES['pic']['tmp_name']); $x++ ) {
$file_name = $_FILES['pic']['name'][$x];
$file_size = $_FILES['pic']['size'][$x];
$file_tmp = $_FILES['pic']['tmp_name'][$x];
$t = explode(".", $file_name);
$t1 = end($t);
$file_ext = strtolower(end($t));
$ext_boleh = array("jpg", "jpeg", "png", "gif", "bmp");
if(in_array($file_ext, $ext_boleh)) {
$dir = 'uploads/';
$sumber = $file_tmp;
move_uploaded_file($sumber, $dir.$file_name);
$sql2 = "UPDATE project_detail SET pic = :pic WHERE no = '$no'";
$statement1 = $connection->prepare($sql2);
if ($statement1->execute([':pic' => $file_name])){ ?>
<script>
alert("new record uploded successfully");
window.location.href=('project.php');
</script>
<?php }
}else {
echo "Only Images can be store!";
}
}
?>
If I've understood correctly ( though I'm still confused by the update satement rather than an insert statement ) then a little re-writing to perform all the upload actions before trying to write to the db should work.
<?php
$images=[];
for( $x=0; $x < count( $_FILES['pic']['tmp_name'] ); $x++ ) {
$file_name = $_FILES['pic']['name'][$x];
$file_size = $_FILES['pic']['size'][$x];
$file_tmp = $_FILES['pic']['tmp_name'][$x];
/* Less complicated and more reliable method to find the file extension!! */
$file_ext = strtolower( pathinfo( $file_name, PATHINFO_EXTENSION ) );
$ext_boleh = array( 'jpg', 'jpeg', 'png', 'gif', 'bmp' );
if( in_array( $file_ext, $ext_boleh ) ) {
$dir = 'uploads/';
$status = move_uploaded_file( $file_tmp, $dir . $file_name );
/*
if the file was moved OK then add it's name
to the images array - this will be used in
the sql later...
*/
if( $status )$images[]=$file_name;
}
}
/*
Where does `$no` come from?
Construct update ( or insert? ) sql statement
making sure we do not leave potential injection
possibilities....!
*/
$sql2 = 'UPDATE `project_detail` SET `pic` = :pic WHERE `no` = :no';
$statement1 = $connection->prepare( $sql2 );
/* Concatenate the image names into a comma separated string */
$args = array(
':pic' => implode(',', $images ),
':no' => $no
);
$result = $statement1->execute( $args );
if( $result ){
/* do a happy dance */
} else {
/* weep */
}
?>
I'm creating a form to upload a file, using yii and php 5.5.3. Here is my code in the controller:
foreach($_FILES['settings']['name'] as $settingName => $value) {
$setting = Setting::model()->find('setting_name=:name', array(':name' => $settingName));
$setting->image_file = CUploadedFile::getInstanceByName('settings['.$settingName.']');
if (!empty($setting->image_file)) {
$extension = "jpg";
$filename = "";
if (($pos = strrpos($setting->image_file, '.')) !== FALSE) {
$extension = substr($setting->image_file, $pos + 1);
$filename = substr($setting->image_file, 0, $pos)."_".strtotime("now");
}
if (!file_exists("uploads") and !is_dir("uploads"))
mkdir("uploads", 0777, TRUE);
$setting->image_file->saveAs("uploads/" . $filename.".".$extension, false);
$setting->setting_value = "uploads/" . $filename.".".$extension;
$setting->save();
}
}
image_file is an extra attribute in model:
array('image_file', 'file', 'types' => 'gif, jpg, jpeg, png', 'maxSize' => 1024 * 1024, 'tooLarge' => 'File upload must not exceed 1MB.'),
and here is the view:
<input type="file" name="settings[store_logo]" class="input-small">
$setting->image_file->saveAs can successfully upload the file, but it also generates
Error 500 Creating default object from empty value
What went wrong? Any help would be much appreciated.
i guess, the $_FILES['settings']['name'] has a empty value in the last Key.
If you upload a File(s), they will be process as expected. The last value in your POST-array cause a NULL-return here:
// $setting === null
$setting = Setting::model()->find('setting_name=:name', array(':name' => $settingName))
and this call throws the 500.
$setting->image_file = CUploadedFile::getInstanceByName('settings['.$settingName.']');
This is my Version of your code:
<?php
foreach($_FILES['settings']['name'] as $settingName => $value) {
$setting = Setting::model()->find('setting_name=:name', array(':name' => $settingName));
// catch null-return
if(!$setting) {
echo "can't find stuff at<pre>"; print_r($settingName); echo "</pre>";
continue;
}
$setting->image_file = CUploadedFile::getInstanceByName('settings['.$settingName.']');
if ($setting->image_file) {
$extension = "jpg";
$filename = "";
if (($pos = strrpos($setting->image_file, '.')) !== FALSE) {
$extension = substr($setting->image_file, $pos + 1);
$filename = substr($setting->image_file, 0, $pos)."_".strtotime("now");
}
if (!file_exists("uploads") and !is_dir("uploads"))
// dont 0777!
mkdir("uploads", 0740, TRUE);
$setting->image_file->saveAs("uploads/" . $filename.".".$extension, false);
$setting->setting_value = "uploads/" . $filename.".".$extension;
$setting->save();
}
}
?>
I've been struggling with this for a while now and hoping someone can point me in the right direction. I have a script that works for uploading a single image. I'm now trying to amed it so that I can update more than 1 file at once. 2 in the example below. I understand that name needs to be an array and I loop through them however I only seem to be encountering errors. I've read and tried various different things.
I either was able to upload one file but not the second, upload no files or a blank white screen.
Below is what I'm currently working with after having various edits.
<?php
$upload_dir= 'training/trainingDocuments';
$numUploads = 2;
$msg = 'Please select files for uploading';
$errors = array();
if(isset($_FILES['myTrainingFile']['tmp_name']))
{
for($i=0; $i < count($_FILES['myTrainingFile']['tmp_name']);$i++)
{
$fileName = $_FILES['myTrainingFile']['name'][$i];
$tempName = $_FILES['myTrainingFile']['tmp_name'][$i];
$blacklist = array('exe','php','jsp','js','bat','asp','aspx','com','dmg');
$a = explode('.', $fileName);
$fileExt = strtolower(end($a)); unset($a);
$fileSize = $_FILES['myTrainingFile']['size'];
if(in_array($fileExt, $blacklist) === true){
$errors[] = "File type not allowed";
}
//$newPath = $general->fileNewPath($path, $fileName);
$newPath = "training/trainingDocuments/" . $_FILES['myTrainingFile']['name'][$i];
$moveFileResult = move_uploaded_file($tempName, $newPath);
if($moveFileResult != true){
$errors[] = 'Upload Failed - MOVE';
}
$comments = htmlentities(trim($_POST['comments']));
$category = htmlentities(trim($_POST['category']));
//insert into db
$training->uploadDocument($fileName, $category, $comments);
if(!is_uploaded_file($_FILES['myTrainingFile']['name'][$i]))
{
$errors[] = 'Uploading '.$_FILES['myTrainingFile']['name'][$i] . 'failed -.-';
}
}
}
?>
Thanks for any help!
Try this code, i added a function named convert_files, so you can handle your uploads in a better way
Code:
<?php
$upload_dir = "training/trainingDocuments";
$numUploads = 2;
$msg = "Please select file(s) for uploading";
$errors = array();
// how many files you want to upload
$maxFiles = 3;
if ( $files = convert_files( $_FILES["myTrainingFile"] ) ) {
foreach( $files as $i => $file ) {
$fileName = $file["name"];
$tempName = $file["tmp_name"];
$fileSize = $file["size"];
// get file extension, and do strtolower
$fileExt = strtolower( pathinfo( $fileName, PATHINFO_EXTENSION ) );
// invalid file types
$blacklist = array( 'exe','php','jsp','js','bat','asp','aspx','com','dmg' );
// new path to upload current file
$newPath = "training/trainingDocuments/".$fileName;
// Check whether its a valid file or invalid file
if ( in_array( $fileExt, $blacklist ) ) {
// invalid file type, add error
$errors[$i] = "File type not allowed";
}
if ( !is_uploaded_file( $tempName ) ) {
// its'' not an uploaded file, add error
$errors[$i] = "Uploading ".$fileName." failed -.-";
}
if ( file_exists( $newPath ) ) {
// file already exists in your directory, add error
$errors[$i] = "File ".$fileName." already exists";
// if you dont want to add error, (adding an error will not upload file)
// just comment above line, and uncomment below line
/*
// get the filename without extension
$name = pathinfo( $fileName, PATHINFO_FILENAME );
//create new file name
$fileName = $name."_".uniqid().".".$fileExt;
//update upload path
$newPath = "training/trainingDocuments/".$fileName;
*/
}
// make sure $errors[$i] contains any errors
if ( isset( $errors[$i] ) ) {
// errors occured, so continue to next file
continue;
}
if ( !move_uploaded_file( $tempName, $newPath ) ) {
$errors[$i] = "Upload Failed - MOVE"; // failed to move file
}
$comments = htmlentities( trim( $_POST['comments'] ) );
$category = htmlentities( trim( $_POST['category'] ) );
// Upload document
$training->uploadDocument( $fileName, $category, $comments );
// check maximum allowed files limit exceeded
if ( ( $i + 1 ) == $maxFiles ) {
// limit exceeded, break the execution
break;
}
}
}
?>
Function:
<?php
function convert_files( $files ) {
if ( is_array( $files ) && !empty( $files["name"] ) ) {
if ( is_array( $files["name"] ) ) {
$merged = array();
foreach( $files["name"] as $i => $name ) {
$merged[] = array(
"name" => $name,
"type" => $files["type"][$i],
"size" => $files["size"][$i],
"error" => $files["error"][$i],
"tmp_name" => $files["tmp_name"][$i]
);
}
return $merged;
}
return array( $files );
}
return false;
}
?>
Form:
//excerpt
$file = new Zend_Form_Element_File('file');
$file->setLabel('File to upload:')
->setRequired(true)
->addValidator('NotEmpty')
->addValidator('Count', false, 1)
->setDestination(APPLICATION_UPLOADS_DIR);
$this->addElement($file);
Controller:
//excerpt
if ($form->isValid($request->getPost()) {
$newFilename = 'foobar.txt';
//how should I rename the file?
//When should I rename the file? Before or after receiving?
try {
$form->file->receive();
echo 'filename: '. $form->file->getFileName();
}
}
Questions:
When I call $form->file->getFileName() it returns the full path, not just the file name. How can I output just the name of the file?
//Answer: First, get an array of the parts of the filename:
$pathparts = pathinfo($form->file->getFileName());
//then get the part that you want to use
$originalFilename = $pathparts['basename'];
How can I rename the filename to something I want? Can this be done with the Rename filter? I'm already setting the destination in the form, so all I want to do is change the filename. Maybe I shouldn't be setting the destination in the form? Or maybe this can't be done with a filter. Maybe I should be doing this with a PHP function? What should I do?
//Answer: Use the rename filter:
$form->file->addFilter('Rename', 'new-file-name-goes-here.txt');
Final Solution:
This is what I ended up doing:
public function foobarAction()
{
//...etc...
if (!$form->isValid($request->getPost())) {
$this->view->form = $form;
return;
}
//the following will rename the file (I'm setting the upload dir in the form)
$originalFilename = pathinfo($form->file->getFileName());
$newFilename = 'file-' . uniqid() . '.' . $originalFilename['extension'];
$form->file->addFilter('Rename', $newFilename);
try {
$form->file->receive();
//upload complete!
$file = new Default_Model_File();
$file->setDisplayFilename($originalFilename['basename'])
->setActualFilename($newFilename)
->setMimeType($form->file->getMimeType())
->setDescription($form->description->getValue());
$file->save();
} catch (Exception $e) {
//error: file couldn't be received, or saved (one of the two)
}
}
Use the rename filter.
To answer question 1, to get a filename from a full path, you can use basename, or pathinfo.
For example (copy-paste from the doc) :
$path = "/home/httpd/html/index.php";
$file = basename($path); // $file is set to "index.php"
Or :
$path_parts = pathinfo('/www/htdocs/index.html');
echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['extension'], "\n";
echo $path_parts['filename'], "\n"; // since PHP 5.2.0
To rename / move the file, I suppose rename would do the trick, even if it's quite not "Zend Framework solution".
If the file has not been moved by ZF and is still in the temporary directory, you should use move_uploaded_file -- but as you are using setDestination, I suppose the file is no longer in the sytem's temporary directory.
Folks, here's a simple example of a form that uses the rename filter on a file after it's been uploaded. There are many more options and yes, you'd need to take in to consideration existing files, but to get you started, here you go.
When the file's uploaded through the form below, it will be renamed to 'config.ini'.
$form = new Zend_Form;
$form->setAction('/default/index/file-upload')
->setMethod('post');
$uploadFile = new Zend_Form_Element_File('uploadfile');
$uploadFile->addFilter(new Zend_Filter_File_Rename(
array('target' => 'config.ini'))
)
->setRequired(true)
->setLabel('Upload file:');
$form->addElement($uploadFile);
$form->addElement(new Zend_Form_Element_Submit('submit'));
if ($form->isValid($_POST)) {
$values = $form->getValues();
}
Easy fix to get Zend to rename before uploading
The problem I address here is explained in more detail here: http://www.thomasweidner.com/flatpress/2009/04/17/recieving-files-with-zend_form_element_file/
I was having trouble getting the file to rename before uploading and found the solution for my scenario. At some point Zend thought it clever to have the getValue() method of the file element upload the file for you. Fortunately they added an option to disable this feature.
Solution: If you are calling getValue() on the file element, or getValues() on the form, and you want to modify the name before it uploads you have to set setValueDisabled(true) on your Zend_Form_Element_File.
Fyi: I don't claim this to be optimized, I just claim it to work for me
Creating the form element (magic inside)
$uploadConfig = Zend_Registry::get('upload');
$fileuploader = new Zend_Form_Element_File('ugc_fileupload');
$fileuploader->setRequired(true);
$fileuploader->setLabel('*Upload File:');
$fileuploader->addValidator('Count', false, 1); // ensure only 1 file
$fileuploader->setValueDisabled(true); // ***THIS IS THE MAGIC***
$fileuploader->addValidator('Size', false, $uploadConfig['videomax']);
$fileuploader->addValidator('Extension', false, 'mov, avi, wmv, mp4');
$this->addElement($fileuploader, 'ugc_fileupload');
Rename before uploading (inside preUpload($form))
$uploadCfg = Zend_Registry::get('upload');
// Get the parts of the name
// Call to getValue() here was uploading the file before telling it not to!
$atiFile = $form->ugc_fileupload->getValue();
$fileExt = $this->getFileExtension($atiFile);
$nameBase = $this->getFileName($atiFile, $fileExt);
$fullName = $atiFile;
$fullPath = $uploadCfg['tmpdir'] . $fullName;
// Keep checking until the filename doesn't exist
$numToAdd = 0;
while(file_exists($fullPath)) {
$fullName = $nameBase . $numToAdd . $fileExt;
$fullPath = $uploadCfg['tmpdir'] . $fullName;
$numToAdd++;
}
$upload = new Zend_File_Transfer_Adapter_Http();
// or $upload = $form->ugc_fileupload->getTransferAdapter();
// both work, I'm not sure if one is better than the other...
//Now that the file has not already been uploaded renaming works
$upload->addFilter(new Zend_Filter_File_Rename(array(
'target' => $fullPath,
'overwrite' => false)
));
try {
$upload->receive();
} catch (Zend_File_Transfer_Exception $e) {
//$e->getMessage()
}
Helper methods
public function getFileName($path, $ext) {
return $bname = basename($path, $ext);
}
public function getFileExtension($path) {
return $ext = strrchr($path, '.');
}
This is difficult to do with Zend for a few reasons.
If you rename the file after it's been moved to the upload destination then it might've overwritten a file that you didn't want rewritten.
For example, say you have a destination directory called /path/to/my/pics. If two users, at the same time, upload a picture called 'me.png' then they might override each other. This is because the rename filter is applied AFTER the file is moved to /path/to/my/pics. Thus, it might not be renamed before it is overwritten by a new file upload.
If you use Zend's rename filter then you can't keep the original files extension.
The way I did it was to do the following,
1. Extend the http transfer adapter to pass the rename filter the original file name. The normal http transfer adapter passes in the temporary name in the tmp directory and does not have the file extension.
Extend the rename filter so that you can specify whether or not it should keep the original file extension.
Afterward, you'll have to add the prefix to the form you're using so that the form can find your adapter and so your adapter can find the new Rename filter you've made.
The reason I did it this way is because my destination directory was going to have one pic in it for every user where each pic was named 'user1.jpg' or 'user2.png'. I wanted to rename the file at the same time that I moved it so it wouldn't override any other files in the directory that I wanted to keep.
Here is the code I've used.
class My_File_Transfer_Adapter_Http
extends Zend_File_Transfer_Adapter_Http
{
/**
* Receive the file from the client (Upload)
* This differs from the Zend adapter in that
* the adapter passes in the files actual
* name to the rename filter so that when
* it is renamed, the renamer can use the extension
* of the file and keep it or change it.
*
* #param string|array $files (Optional) Files to receive
* #return bool
*/
public function receive($files = null)
{
if (!$this->isValid($files)) {
return false;
}
$check = $this->_getFiles($files);
foreach ($check as $file => $content) {
if (!$content['received']) {
$directory = '';
$destination = $this->getDestination($file);
if ($destination !== null) {
$directory = $destination . DIRECTORY_SEPARATOR;
}
/******************************************/
// The original transfer adapter
// passes content['tmp_name']
// but we'll pass in content['name'] instead
// to have access to the extension
/******************************************/
$filename = $directory . $content['name'];
$rename = $this->getFilter('File_Rename');
if ($rename !== null) {
$tmp = $rename->getNewName($content['name']);
if ($tmp != $content['name']) {
$filename = $tmp;
}
if (dirname($filename) == '.') {
$filename = $directory . $filename;
}
$key = array_search(get_class($rename), $this->_files[$file]['filters']);
unset($this->_files[$file]['filters'][$key]);
}
// Should never return false when it's tested by the upload validator
if (!move_uploaded_file($content['tmp_name'], $filename)) {
if ($content['options']['ignoreNoFile']) {
$this->_files[$file]['received'] = true;
$this->_files[$file]['filtered'] = true;
continue;
}
$this->_files[$file]['received'] = false;
return false;
}
if ($rename !== null) {
$this->_files[$file]['destination'] = dirname($filename);
$this->_files[$file]['name'] = basename($filename);
}
$this->_files[$file]['tmp_name'] = $filename;
$this->_files[$file]['received'] = true;
}
if (!$content['filtered']) {
if (!$this->_filter($file)) {
$this->_files[$file]['filtered'] = false;
return false;
}
$this->_files[$file]['filtered'] = true;
}
}
return true;
}
}
That is the adapter, now for the filter.
class My_Filter_File_Rename
extends Zend_Filter_File_Rename
{
/**
* Internal array of array(source, target, overwrite)
*/
protected $_files = array( );
/**
* Class constructor
*
* Options argument may be either a string, a Zend_Config object, or an array.
* If an array or Zend_Config object, it accepts the following keys:
* 'source' => Source filename or directory which will be renamed
* 'target' => Target filename or directory, the new name of the sourcefile
* 'overwrite' => Shall existing files be overwritten ?
* 'keepExtension' => Should the files original extension be kept
*
* #param string|array $options Target file or directory to be renamed
* #param string $target Source filename or directory (deprecated)
* #param bool $overwrite Should existing files be overwritten (deprecated)
* #return void
*/
public function __construct( $options )
{
if( $options instanceof Zend_Config )
{
$options = $options->toArray();
}
elseif( is_string( $options ) )
{
$options = array( 'target' => $options );
}
elseif( !is_array( $options ) )
{
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception( 'Invalid options argument provided to filter' );
}
if( 1 setFile( $options );
}
/**
* Returns the files to rename and their new name and location
*
* #return array
*/
public function getFile()
{
return $this->_files;
}
/**
* Sets a new file or directory as target, deleting existing ones
*
* Array accepts the following keys:
* 'source' => Source filename or directory which will be renamed
* 'target' => Target filename or directory, the new name of the sourcefile
* 'overwrite' => Shall existing files be overwritten ?
* 'keepExtension' => Should the files original extension be kept
*
* #param string|array $options Old file or directory to be rewritten
* #return Zend_Filter_File_Rename
*/
public function setFile( $options )
{
$this->_files = array( );
$this->addFile( $options );
return $this;
}
/**
* Adds a new file or directory as target to the existing ones
*
* Array accepts the following keys:
* 'source' => Source filename or directory which will be renamed
* 'target' => Target filename or directory, the new name of the sourcefile
* 'overwrite' => Shall existing files be overwritten ?
* 'keepExtension' => Should the files original extension be kept
*
* #param string|array $options Old file or directory to be rewritten
* #return Zend_Filter_File_Rename
*/
public function addFile( $options )
{
if( is_string( $options ) )
{
$options = array( 'target' => $options );
}
elseif( !is_array( $options ) )
{
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception( 'Invalid options to rename filter provided' );
}
$this->_convertOptions( $options );
return $this;
}
/**
* Returns only the new filename without moving it
* But existing files will be erased when the overwrite option is true
*
* #param string $value Full path of file to change
* #param boolean $source Return internal informations
* #return string The new filename which has been set
*/
public function getNewName( $value,
$source = false )
{
$file = $this->_getFileName( $value );
if( $file[ 'source' ] == $file[ 'target' ] )
{
return $value;
}
if( !file_exists( $file[ 'source' ] ) && !$file['keepExtension'] )
{
return $value;
}
if( ($file[ 'overwrite' ] == true) && (file_exists( $file[ 'target' ] )) )
{
unlink( $file[ 'target' ] );
}
if( file_exists( $file[ 'target' ] ) )
{
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception( sprintf( "File '%s' could not be renamed. It already exists.",
$value ) );
}
if( $source )
{
return $file;
}
return $file[ 'target' ];
}
/**
* Defined by Zend_Filter_Interface
*
* Renames the file $value to the new name set before
* Returns the file $value, removing all but digit characters
*
* #param string $value Full path of file to change
* #throws Zend_Filter_Exception
* #return string The new filename which has been set, or false when there were errors
*/
public function filter( $value )
{
$file = $this->getNewName( $value, true );
if( is_string( $file ) )
{
return $file;
}
$result = rename( $file[ 'source' ], $file[ 'target' ] );
if( $result === true )
{
return $file[ 'target' ];
}
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception( sprintf( "File '%s' could not be renamed. An error occured while processing the file.",
$value ) );
}
/**
* Internal method for creating the file array
* Supports single and nested arrays
*
* #param array $options
* #return array
*/
protected function _convertOptions( $options )
{
$files = array( );
foreach( $options as $key => $value )
{
if( is_array( $value ) )
{
$this->_convertOptions( $value );
continue;
}
switch( $key )
{
case "source":
$files[ 'source' ] = ( string ) $value;
break;
case 'target' :
$files[ 'target' ] = ( string ) $value;
break;
case 'overwrite' :
$files[ 'overwrite' ] = ( boolean ) $value;
break;
case 'keepExtension':
$files[ 'keepExtension' ] = ( boolean ) $value;
break;
default:
break;
}
}
if( empty( $files ) )
{
return $this;
}
if( empty( $files[ 'source' ] ) )
{
$files[ 'source' ] = '*';
}
if( empty( $files[ 'target' ] ) )
{
$files[ 'target' ] = '*';
}
if( empty( $files[ 'overwrite' ] ) )
{
$files[ 'overwrite' ] = false;
}
if( empty( $files[ 'keepExtension' ] ) )
{
$files[ 'keepExtension' ] = true;
}
$found = false;
foreach( $this->_files as $key => $value )
{
if( $value[ 'source' ] == $files[ 'source' ] )
{
$this->_files[ $key ] = $files;
$found = true;
}
}
if( !$found )
{
$count = count( $this->_files );
$this->_files[ $count ] = $files;
}
return $this;
}
/**
* Internal method to resolve the requested source
* and return all other related parameters
*
* #param string $file Filename to get the informations for
* #return array
*/
protected function _getFileName( $file )
{
$rename = array( );
foreach( $this->_files as $value )
{
if( $value[ 'source' ] == '*' )
{
if( !isset( $rename[ 'source' ] ) )
{
$rename = $value;
$rename[ 'source' ] = $file;
}
}
if( $value[ 'source' ] == $file )
{
$rename = $value;
}
}
if( !isset( $rename[ 'source' ] ) )
{
return $file;
}
if( !isset( $rename[ 'target' ] ) or ($rename[ 'target' ] == '*') )
{
$rename[ 'target' ] = $rename[ 'source' ];
}
if( is_dir( $rename[ 'target' ] ) )
{
$name = basename( $rename[ 'source' ] );
$last = $rename[ 'target' ][ strlen( $rename[ 'target' ] ) - 1 ];
if( ($last != '/') and ($last != '\\') )
{
$rename[ 'target' ] .= DIRECTORY_SEPARATOR;
}
$rename[ 'target' ] .= $name;
}
if( !is_dir( $rename['target'] ) || $rename[ 'keepExtension' ] )
{
$name = basename( $rename[ 'source' ] );
$parts = explode( '.', $name );
$extension = $parts[count( $parts ) - 1];
$rename[ 'target' ] .= '.' . $extension;
}
return $rename;
}
}
You'll then have to add the prefix path's to the file element that you've made to upload the file.
$fileElement->addPrefixPath('My_File_Transfer_Adapter', 'My/File/Transfer/Adapter', Zend_Form_Element_File::TRANSFER_ADAPTER );
$fileElement->addPrefixPath( 'My_Filter', 'My/Filter', Zend_Form_Element_File::FILTER );
When you add the filter to the file element you'll have to do it the following way
$fileElement->addFilter(
'File_Rename',
array(
'target' => $this->_getPictureDestination() . DIRECTORY_SEPARATOR . "user$userId",
'overwrite' => true,
'keepExtension' => true
)
)
Now, when the files get moved over to the new directory they'll have the original files extension and they'll have the new name that you specified when you added the filter to the file element.
If this was hard to understand please let me know. It took me a while to figure out what was going on in Zend to do this so if it helps anyone, use this code freely.
// For Zend Framework :: Rename Uploaded File
$renameFile = 'newName.jpg';
$fullFilePath = '/images/'.$renameFile;
// Rename uploaded file using Zend Framework
$filterFileRename = new Zend_Filter_File_Rename(array('target' => $fullFilePath, 'overwrite' => true));
$filterFileRename -> filter($name);
You can use Rename filter. If you want to rename your filename during uploading maybe it helps you.
First we need a function rename or remove unwanted characters from your filename for example use this.
public function simple_fileformat($str)
{
$str = preg_replace("{[^A-Za-z0-9_]\.}", "", $str);
$str = str_replace(" ", "_", $str);
return $str;
}
After that you can use the above function for renaming.
$filename = new Zend_Form_Element_File("filename");
$filename->setLabel("filename");
$filename->setRequired(true);
$filename->setDestination($doc_path);
$filename->addFilter("rename", $doc_path . DIRECTORY_SEPARATOR . $this->simple_fileformat(basename($filename->getFileName())));
That is easy. Is not it?