addFilter Rename ZendFramework - zend-framework

i need to Rename a file with Zend_File_Transfer() only if new file match with old one in the server using some convention like newfile-1.ext where the -1 is the string that is added but Rename filter is strange, i really dont understand so good.
For example, is necesary some like this:
if(file_exists($file)){
$upload->addFilter('Rename', $file);
}
or Rename does it?
thanks

Here is an example from one of my apps. File is recvieved by an Zend_Form
$upload->receive();
$name = $upload->getFileName();
$newFile = 'mynewfile.xyz'
$filterFileRename = new Zend_Filter_File_Rename(array(
'target' => $this->path . $newFile, // path to file
'overwrite' => true
));
$file = $filterFileRename->filter($name);

Related

Typo3 : add file to FAL when it is not presente in sys_file

I have this situation
I have a table in my db containing some file names in a field1 (eg field1: "my file.ext")
NOTE: the filename does not necessarily pass a Typo3 "sanitizeFilename" check -> it may contain spaces " " or other characters that would be removed by the sanitizeFilename () method
I have the file mentioned above, stored on the server that host typo3
In the sys_file table, the file is not present
the "update storage index" scheduler cannot process all the files, and if i launch it, it "destroy" the file name (my file.ext -> my_file.ext), so the name stored in the field of my table doensn't have much sense anymore.
I would need to absorb the above mentioned files in the FAL, in order to use them in an ext typo3.
I had thought of such a solution
<?php
// read from "field1" of my table
// $filename = the name extracted from my table (e.g. : "my file.ext")
// %path = the path of the file : e.g. "/fileadmin/user_upload")
if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/" . $defaultStorage->getConfiguration()['basePath'] . $path . $filename)) {
// check the folder
if ($defaultStorage->hasFolder($path)) {
$folder = $defaultStorage->getFolder($path);
} else {
throw new \ Exception ($path . "path not found in AbstractImportCommand in method extractFile");
}
// CHECK IF FILE IS IN FAL
$file = $folder->getStorage()->getFileInFolder($filename, $folder);
if ($file) {
// the file already exists in the FAL
} else {
// create new sys_file
$file = $defaultStorage->addFile(
$_SERVER['DOCUMENT_ROOT'] . "/" . $defaultStorage->getConfiguration()['basePath'] . $path . $filename,
$folder,
DuplicationBehavior::REPLACE
);
}
}
Any suggestion?
Put your code into a command.
(optional) create a sys_file_metadata record for your file if you have information that needs to be stored there
create a sys_file_reference to your content record (before that you should adjust TCA accordingly)
For creating the sys_file_reference there is no api. A function doing so could look like this:
/**
* #param $fileUid
* #param $recordUid
* #param $table
*/
private function createSysFileReference($record, $fileUid, $tableName, $fieldName){
$data['sys_file_reference']['NEW_' . uniqid()] = [
'table_local' => 'sys_file',
'uid_local' => $fileUid,
'tablenames' => $tableName,
'uid_foreign' => $record['uid'],
'fieldname' => $fieldName,
'pid' => $record['pid']
];
$dataHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
$dataHandler->start($data, []);
$dataHandler->process_datamap();
}
What you consider as "destroying the filename" is indeed preserving file functionality, so sanitizing the filenames is required.
As example consider a file with white space like "My Pdf.pdf". It will be shown eventually like "My%20Pdf.pdf" in the URL and also saved like this. If you link to it, at least the link text won't show the "%20" and the expectation that links and the name of the file are always synchronized (no matter how it's stored) isn't reliable as it probably depends on several parameters like operating system or browser too. The same problem might occur for many different signs too.
Consider that the problems occur not only when a user is downloading a file but also when a file is uploaded, where the wrong url-encoded name is saved in the database, this name might be saved differently in the filesystem or not be found even if the saved value is the same as in the filesystem, due to the url-encoded signs. Your file references are broken on the server then and according links might not work and images not displayed.
So circumventing FAL beside tables is a bad decision and while it's likely possible to write an own sanitizer, I would refrain from dropping it completely.

Send file to Restful service in codeception

I would like to test restful API test for file uploading.
I try to run:
$I->sendPOST($this->endpoint, $postData, ['file' => 'example.jpg']);
and I would like it to behave the same as user sent example.jpg file in file input with name file but it doesn't seem to work this way. I'm getting:
[PHPUnit_Framework_ExceptionWrapper] An uploaded file must be an array or an instance of UploadedFile.
Is it possible to upload file using REST plugin in codeception? Documentation is very limited and it's hard to say how to do it.
I'm also testing API using Postman plugin to Google Chrome and I can upload file without a problem using this plugin.
I was struggling with the same problem recently and found out that there is another way to solve the issue without using Symfony's UploadedFile class. You only need to pass the array with file data in the same format as if it were the $_FILES array. For example, this code works perfectly well for me:
$I->sendPOST(
'/my-awesome-api',
[
'sample-field' => 'sample-value',
],
[
'myFile' => [
'name' => 'myFile.jpg',
'type' => 'image/jpeg',
'error' => UPLOAD_ERR_OK,
'size' => filesize(codecept_data_dir('myFile.jpg')),
'tmp_name' => codecept_data_dir('myFile.jpg'),
]
]
);
Hope this helps someone and prevents from inspecting the framework's source code (which I was forced to do, as the docs skip such an important detail)
After testing it seems to make it work we need to use UploadedFile object as file.
For example:
$path = codecept_data_dir();
$filename = 'example-image.jpg';
// copy original test file to have at the same place after test
copy($path . 'example.jpg', $path . $filename);
$mime = 'image/jpeg';
$uploadedFile = new \Symfony\Component\HttpFoundation\File\UploadedFile($path . $filename, $filename, $mime,
filesize($path . $filename));
$I->sendPOST($this->endpoint, $postData, ['file' => $uploadedFile]);
['file' => 'example.jpg'] format works too, but the value must be a correct path to existing file.
$path = codecept_data_dir();
$filename = 'example-image.jpg';
// copy original test file to have at the same place after test
copy($path . 'example.jpg', $path . $filename);
$I->sendPOST($this->endpoint, $postData, ['file' => $path . $filename]);
The below worked for myself,
On server:
$uploadedResume= $_FILES['resume_uploader'];
$outPut = [];
if (isset($uploadedResume) && empty($uploadedResume['error'])) {
$uploadDirectory = 'uploads/users/' . $userId . '/documents/';
if (!is_dir($uploadDirectory)) {
#mkdir($uploadDirectory, 0777, true);
}
$ext = explode('.', basename($uploadedResume['name']));
$targetPath = $uploadDirectory . md5(uniqid()) . '.' . end($ext);
if (move_uploaded_file($uploadedResume['tmp_name'], $targetPath)) {
$outPut[] = ['success' => 'success', 'uploaded_path' => $targetPath];
}
}
return json_encode($output);
Sorry for the long description code :P
On Testing side:
//resume.pdf is copied in to tests/_data directory
$I->sendPOST('/student/resume', [], ['resume_uploader' => codecept_data_dir('resume.pdf') ]);
#Yaronius's answer worked for me after I removed the following header from my test:
$I->haveHttpHeader('Content-Type', 'multipart/form-data');

Zend_Form_Element_File multiple file upload and mysql

Does anybody knows a working example to receive multiple files, store them in a folder and the names in a mysql table? Some days already with no luck at all, something always missing, and before putting those questions, well , maybe i can find the right one!
maybe?
i am learning using zend 1.11
thanks
pablo
EDIT:
i add the code for clearness:
in the form:
$element = new Zend_Form_Element_File('images');
$element->setLabel('Upload bis 3 Bilder (máx. 200kb each):')
->setMultiFile(3)
->setValueDisabled(true)
->addValidator(new Zend_Validate_File_Size('2MB'))
->addValidator('Count', false, array('min'=>0,'max' => 3));
in the controller:
$adapter = $form->images->getTransferAdapter();
//create directory where files would be hold
if (!file_exists(UPLOADDIR))
mkdir(UPLOADDIR, 0777, 1);
$i=0;
$images="";
//loop uploaded files
foreach ($adapter->getFileInfo() as $info)
{
//rename file how you like and move it to given destination
$fileName = time().$i.'.'.$this->getExtension($info['name']);
$adapter->addFilter('Rename', array('target'=>UPLOADDIR.$fileName, 'overwrite'=>true));
//if something goes wrong print errors in screen
if (!$adapter->receive($info['name']))
{
die(print_r($adapter->getMessages(),1));
}else{
if ($info['name']!==""){
$images .= $fileName.",";
}
}
$i++;
}
I think you should use setFilters() instead of addFilter on the adapter, because the current code will add a new Rename filter on each iteration of the foreach loop.
Try replacing:
$adapter->addFilter('Rename', array('target'=>UPLOADDIR.$fileName, 'overwrite'=>true));
with
$adapter->setFilters(array(new Zend_Filter_File_Rename(array('target'=>UPLOADDIR.$fileName, 'overwrite'=>true))));

Zend_Translate, set up the log via the application resource plugin?

I'm using application resource plugins in a .ini file to set up my Zend_Translate with this code:
resources.translate.data = APPLICATION_PATH "/../languages"
resources.translate.adapter = "gettext"
resources.translate.options.scan = "directory"
Now I would like to add the log functionality to the translate, which in bootstrap I would do like this:
$writer = new Zend_Log_Writer_Stream( APPLICATION_PATH . '/../logs/translate.log');
$log = new Zend_Log($writer);
$translate->setOptions(
array(
'log' => $log,
'logUntranslated' => true
)
);
2 questions about this:
First, is it possible to this in the .ini file?
Secondly, it is possible to "extend" resource settings in the bootstrap? In other words, could I add for example this log option in the bootstrap to the translate while maintaining the other settings already made in the .ini file?
Alright, I haven't found a solution to this in the ini file, but I have found a way to "extend" my settings from the ini file in the bootstrap without overwriting them. I managed to do that like this:
protected function _initTranslate()
{
$writer = new Zend_Log_Writer_Stream( APPLICATION_PATH . '/../somedir/somefile.log');
$log = new Zend_Log($writer);
// get the translate resource from the ini file and fire it up
$resource = $this->getPluginResource('translate');
$translate = $resource->getTranslate();
// add the log to the translate
$translate->setOptions(
array(
'log' => $log,
'logUntranslated' => true
)
);
// return the translate to get it in the registry and so on
return $translate;
}
This works just fine. I'm going to remove the translate from the .ini though because I'm switching to my own adapter and don't know (yet) how to pull that off from the ini.

ZendFramework Zend_Form_Element_File setDestination vs rename filter

The code says Zend_Form_element_File::setDestination() is deprecated and to use the rename filter. However the rename filter is currently codes such that when path is set, only temporary name is given. Original filename is lost.
<?php
$file = new Zend_Form_Element_File();
$file->setDestination('/var/www/project/public');
?>
vs
<?php
$file = new Zend_Form_Element_File();
$file->addFilter('Rename', array('target' => '/var/www/project/public'));
?>
Any solution to upload files so that it preserves original filename structure but checks for existing file and appends _1.ext or _2.ext?
You need to query the name of the file after upload and then add the Rename filter then. Eg:
if ($form->file->isUploaded()) {
$fileinfo = $form->file->getFileInfo();
$filename = $fileinfo['file']['name'];
$extn = pathinfo($filename,PATHINFO_EXTENSION);
$uploadname = $this->_makeFilename($formData, $extn);
$uploadfilepath = UPLOADED_FILES_PATH . '/' . $uploadname;
$form->file->addFilter('Rename', $uploadfilepath);
$receiveStatus = $form->file->receive();
}
After submitting the form you can inspect the $_FILES['file_element']['name'] check for existing files and then set the rename filter on your form element before calling the :
$form->getValues()/isValid() or $form->file_element->receive().