i have an issue with uploading multiple files to disk. here is my code.
i have a request with 2 pictures that gets sent to a upload function. the 2 pictures are in a var called $multiUpload
$folderPath = '/var/www/';
if (is_array($multiUpload)){
$file = array();
$filename = array();
foreach($multiUpload as $key=>$val){
// get the file extension
$file[] = explode('.',$val);
// create custom file name
$filename[] = time().'.'.$file[$key][1];
//send to the upload function
$this->uploadToDisk($folderPath, $filename[$key]);
// sleep 1 sec so that the pic names will be different
sleep(1);
}
return $filename;
}
public function uploadToDisk($folderPath, $filename)
{
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->setDestination($folderPath);
$adapter->addFilter( 'Rename',array(
'target' => $folderPath."/".$filename,
'overwrite' => true
) );
if ($adapter->receive()) {
$message = "success";
} else {
$message = "fail";
}
return $message;
}
this will return
Array
(
[0] => Array
(
[0] => 1332977938.jpg
[1] => 1332977939.jpg
)
)
but only array[0][0] or 1332977938.jpg will actually get saves to the disk.
Why are they now both get saved? wired
any ideas?
I suspect the second call to uploadToDisk is returning fail because you can only call Zend_File_Transfer_Adapter_Http::receive() once for each file. Since you are not specifying a file when calling receive, it is receiving all of the files the first time you call uploadToDisk and subsequently is failing with a File Upload Attack error.
Here is some code you can try. This tries to receive each file individually and then save them one at a time with each call to uploadToDisk.
A few notes about the code:
The first parameter to uploadToDisk ($val) may need to be changed as I am not sure what the original values are. It should correspond to one of the element names used for the file upload (See Zend_File_Transfer_Adapter_Http::getFileInfo()) for a list of the files.
I changed the method for generating a unique filename so you don't have to sleep(1)
Zend_File_Transfer_Adapter_Abstract::setDestination() is deprecated and will go away in the future. Instead, just use the Rename filter. When using Rename, setDestination() has no effect.
And here it is...
<?php
$folderPath = '/var/www/';
if (is_array($multiUpload)){
$filenames = array();
foreach($multiUpload as $key => $val){
// get the file extension
$ext = explode('.', $val);
$ext = $ext[sizeof($ext) - 1];
// create custom file name
do {
$filename = uniqid(time()) . '.' . $ext;
$diskPath = $folderPath . $filename;
} while (file_exists($diskPath));
$filenames[$key] = $filename;
//send to the upload function
// $val is the file to receive, $diskPath is where it will be moved to
$this->uploadToDisk($val, $diskPath);
}
return $filename;
}
public function uploadToDisk($file, $filename)
{
// create the transfer adapter
// note that setDestination is deprecated, instead use the Rename filter
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addFilter('Rename', array(
'target' => $filename,
'overwrite' => true
));
// try to receive one file
if ($adapter->receive($file)) {
$message = "success";
} else {
$message = "fail";
}
return $message;
}
Related
I have a functionality which will get user input and file input in a form and sent it as an email. I am using this code to capture those files:
$attachments_array = NULL;
foreach($_FILES as $userfile){
// store the file information to variables for easier access
$tmp_name = $userfile['tmp_name'];
$type = $userfile['type'];
$name = $userfile['name'];
$size = $userfile['size'];
if($tmp_name != ""){
$data=array(
'tmpfname' => $tmp_name,
'filename' => $name,
'type' => $type,
);
$attachments_array[] = $data;
}
}
So I am getting the user file input and putting it into $attachments_array . But what if I have a fixed file located somewhere like in:
https://www.myurl.com/A_Beginners_Guide_to_Outsourcing.pdf
How do I pass that into the attachments array? I am trying:
$attachments_array[] = file_get_contents('https://www.myurl.com/A_Beginners_Guide_to_Outsourcing.pdf');
But seems not working. I would like to pass it in the attachment array like the $data variable.
file_get_contents only gets the actual content of a file and returns it.
You would need to create an associative array and fill all used parameters by yourself, and perhaps save the file somewhere locally, depending on what are the further steps in your file processing.
$row = array();
$row['filename'] = 'A_Beginners_Guide_to_Outsourcing.pdf';
$row['type'] = "application/pdf"; // you might need some other method of getting a file type.
$tmp_path = "/my/tmp/path/".$row['filename'];
$body = file_get_contents('https://www.myurl.com/A_Beginners_Guide_to_Outsourcing.pdf');
file_put_contents($tmp_path, $body); // btw, be careful of what you save on your server..
$row['tmpfname'] = $tmp_path;
$attachments_array[] = $row;
I have made a form on the front end to upload some images. My idea is to automatically rename all files uploaded into unique id's.
I have looked at the SilverStripe API and I do not see anything about that. UploadField API
Is this possible?
Here is my solution bellow, in Silverstripe 3.X we must extend UploadField with another class. Then copy the ''saveTemporaryFile'' function into it.
Just before ''try'', just have to add :
$ext = array_reverse(explode('.',$tmpFile['name'])); // explode filename into array, reverse array, first array key will then be file extension
$tmpFile['name'] = hash_hmac('sha256', $tmpFile['name'], '12345') . '.' . $ext[0];
Results :
class RandomNameUploadField extends UploadField {
protected function saveTemporaryFile($tmpFile, &$error = null) {
// Determine container object
$error = null;
$fileObject = null;
if (empty($tmpFile)) {
$error = _t('UploadField.FIELDNOTSET', 'File information not found');
return null;
}
if($tmpFile['error']) {
$error = $tmpFile['error'];
return null;
}
// Search for relations that can hold the uploaded files, but don't fallback
// to default if there is no automatic relation
if ($relationClass = $this->getRelationAutosetClass(null)) {
// Create new object explicitly. Otherwise rely on Upload::load to choose the class.
$fileObject = Object::create($relationClass);
}
$ext = array_reverse(explode('.',$tmpFile['name'])); // explode filename into array, reverse array, first array key will then be file extension
$tmpFile['name'] = hash_hmac('sha256', $tmpFile['name'], '12345') . '.' . $ext[0];
// Get the uploaded file into a new file object.
try {
$this->upload->loadIntoFile($tmpFile, $fileObject, $this->getFolderName());
} catch (Exception $e) {
// we shouldn't get an error here, but just in case
$error = $e->getMessage();
return null;
}
// Check if upload field has an error
if ($this->upload->isError()) {
$error = implode(' ' . PHP_EOL, $this->upload->getErrors());
return null;
}
// return file
return $this->upload->getFile();
}
}
Thanks #3dgoo to give me a part of the solution!
I don't now about a API but with some code I was able to do that.
You have two possibilities.
First using database.
Second using only code:
$directory = '/teste/www/fotos/';
$files = glob($directory . '*.jpg');
if ( $files !== false )
{
$filecount = count( $files );
$newid = $filecount+1;
$new_name = "foto_".$newid;
$target_file = $directory."/".$new_name;
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);
}
else
{
$new_name = "foto_1";
$target_file = $directory."/".$new_name;
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);
}
My example is for jpeg but you can look for hall types.
I've recently created a page on our site where users can upload an image and email it to an email address set up specifically to keep the uploaded documents.
I've tested this myself and it works, with the attachments arriving in gmail as expected.
However, whenever someone from outside uses this feature the attachment in the email is unavailable, or not could not be loaded, when we try to open it.
The code is split between 2 files, a controller and a helper. Here's the code (For the sake of saving some space I've removed all error checks, but in the actual code they are all still in place and not picking up any errors whatsoever):
controller
$helper = [GET HELPER];
/** Upload the file to a temp location so that we can attach it to an email */
$uploader = new Varien_File_Uploader('filename');
$uploader->setAllowedExtensions(array(
'image/jpeg',
'image/jpg',
'image/png',
'application/pdf'
))
->setAllowRenameFiles(true)
->setFilesDispersion(false);
$path = $helper->getFileStorageLocation(); // Will store files in /tmp
if (!is_dir($path))
{
mkdir($path, 0775, true);
}
$uploader->save($path, $_FILES['filename']['name']);
$result = $helper->sendMail($_FILES['filename']['name']);
if ($result)
{
$uploadSuccess = true;
/** Remove the temp file */
unlink($path . DS . $_FILES['filename']['name']);
}
helper
/** Declare variables */
$order = Mage::getModel('sales/order')->load($orderId);
$file_incremented_id = $order->getIncrementId();
$copyTo = $this->getCopyTo();
$copyFrom = $this->getCopyFrom();
$subject = 'proof of upload for ' . $file_incremented_id;
$copyTo = explode(',', $copyTo);
$body = '<span>Please see attachment</span>';
$file = $this->getFileStorageLocation() . DS . $filename; // function receives filename from whatever is calling it
$attachment = file_get_contents($file);
$extension = pathinfo($file, PATHINFO_EXTENSION);
if (!$copyTo)
{
return false;
}
$mail = Mage::getModel('core/email_template');
$mail->setSenderName('Uploader');
$mail->setSenderEmail($copyFrom);
$mail->setTemplateSubject($subject);
$mail->setTemplateText($body);
$mail->getMail()->createAttachment(
$attachement,
Zend_Mime::TYPE_OCTETSTREAM,
Zend_Mime::DISPOSITION_ATTACHMENT,
Zend_Mime::ENCODING_BASE64,
$file_incremented_id . '.' . $extension // Set order number as file name
);
try
{
$mail->send($copyTo);
return true;
}
catch (Exception $e)
{
return false;
}
Can anyone see anything that might be causing the issue, or think of what it might be based on my explanation of the setup?
So the problem, in the end, was filesize. My fault for not posting the $_FILES variable.
I saw it a bit later and the variable had error = 1, meaning that the file's size was larger than what was allowed by the max_upload_filesize in the php.ini
I made Joomla admin component according to Joomla guide - http://docs.joomla.org/Developing_a_Model-View-Controller_Component/2.5/Developing_a_Basic_Component
In that i need to have file uploader which let user to upload single file.
In administrator\components\com_invoicemanager\models\forms\invoicemanager.xml i have defined
<field name="invoice" type="file"/>
In the controller administrator\components\com_invoicemanager\controllers\invoicemanager.php im trying to retrieve that file like below. But its not working (can't retrieve file)
Where am i doing it wrong ?
How can i get file and save it on disk ?
class InvoiceManagerControllerInvoiceManager extends JControllerForm
{
function save(){
$file = JRequest::getVar( 'invoice', '', 'files', 'array' );
var_dump($file);
exit(0);
}
}
make sure that you have included enctype="multipart/form-data" in the form that the file is being submitting. This is a common mistake
/// Get the file data array from the request.
$file = JRequest::getVar( 'Filedata', '', 'files', 'array' );
/// Make the file name safe.
jimport('joomla.filesystem.file');
$file['name'] = JFile::makeSafe($file['name']);
/// Move the uploaded file into a permanent location.
if (isset( $file['name'] )) {
/// Make sure that the full file path is safe.
$filepath = JPath::clean( $somepath.'/'.strtolower( $file['name'] ) );
/// Move the uploaded file.
JFile::upload( $file['tmp_name'], $filepath );}
Think i found the solution :)
$file = JRequest::getVar('jform', null, 'files', 'array');
Saving part is mentioned here - http://docs.joomla.org/Secure_coding_guidelines
For uploading the file from your component, you need to write your code in the controller file and you can extend the save() method. check the code given below -
public function save($data = array(), $key = 'id')
{
// Neccesary libraries and variables
jimport('joomla.filesystem.file');
//Debugging
ini_set("display_error" , 1);
error_reporting(E_ALL);
// Get input object
$jinput = JFactory::getApplication()->input;
// Get posted data
$data = $jinput->get('jform', null, 'raw');
$file = $jinput->files->get('jform');
// renaming the file
$file_ext=explode('.',JFile::makeSafe($file['invoice']['name'])); // invoice - file handler name
$filename = round(microtime(true)) . '.' . strtolower(end($file_ext));
// Move the uploaded file into a permanent location.
if ( $filename != '' ) {
// Make sure that the full file path is safe.
$filepath = JPath::clean( JPATH_ROOT."/media/your_component_name/files/". $filename );
// Move the uploaded file.
if (JFile::upload( $file['invoice']['tmp_name'], $filepath )) {
echo "success :)";
} else {
echo "failed :(";
}
$data['name'] = $filename ; // getting file name
$data['path'] = $filepath ; // getting file path
$data['size'] = $file['invoice']['size'] ; // getting file size
}
JRequest::setVar('jform', $data, 'post');
$return = parent::save($data);
return $return;
}
Joomla 2.5 & 3 style:
$app = JFactory::getApplication();
$input = $app->input;
$file= $input->files->get('file');
if(isset($file['name']))
{
jimport('joomla.filesystem.file');
$file['name'] = strtolower(JFile::makeSafe($file['name']));
$fileRelativePath = '/pathToTheRightFolder/'.$file['name'];
$fileAbsolutePath = JPath::clean( JPATH_ROOT.$fileRelativePath);
JFile::upload( $file['tmp_name'], $fileAbsolutePath );
}
http://docs.joomla.org/How_to_use_the_filesystem_package
has a full upload sample.
Little sample where admin choose the file type or all, enter the users to access the form upload. Folder to upload files in Joomla directory or with absolute path. Only selected users access the form upload.
I've got this PHP script I'm working on to import pay-stubs into Drupal. It's doing everything the way I want except the script is not attaching the uploaded PDF file to the node.
A few notes; Drupal's filesystem is set to private, not sure if this makes a difference or not. Second, the pdf files are already in the correct location 'paystubs/[uid]/paystub_1.pdf' so I think my problem is that the file is not being associated to the node correctly.
Here is the code
function create_drupal_node($employeeID, $employeeDate, $drupalUid, $file2) {
$sourcePDF = "/var/www/html/mgldev.************.com/burst_pdfs/pdfs/" . $file2;
$destinationPDF = '/paystubs/' . $drupalUid . '/' . $file2;
$destination = '/paystubs/' . $drupalUid . '/';
if (!file_check_directory($destination, TRUE)){
echo "Failed to check dir, does it exist?";
mkdir($destination);
echo "trying to drupal mkdir...";
}
// Copy the file to the Drupal files directory
if (file_exists($sourcePDF)) {
if(!rename($sourcePDF, $destinationPDF)) {
echo "Failed to move file\n";
}
}
//Create node and attach file uplaod
$file_drupal_path = "paystubs/" . $drupalUid . "/" . $file2;
$mime = 'pdf/application';
$file = new stdClass();
$file->filename = $file2;
$file->filepath = $file_drupal_path;
$file->filemime = $mime;
$file->filesize = filesize($file_drupal_path);
$file->uid = $drupalUid;
$file->status = FILE_STATUS_PERMANENT;
$file->timestamp = time();
drupal_write_record('files', $file);
$node = new StdClass();
$node->type = 'paystub';
$node->body = $employeeID;
$node->title = $employeeDate;
$node->field_paystub_upload = array(
array(
'fid' => $file->fid,
'title' => $file2,
'filename' => $file->filename,
'filepath' => $file->filepath,
'filesize' => $file->filesize,
'mimetype' => $mime,
'data' => array(
'description' => $file2,
),
'list' => 1,
),
);
$node->uid = $drupalUid;
$node->status = 1;
$node->active = 1;
$node->promote = 1;
node_save($node);
}
The node is created and the title and body of the node have the right values. When I look at the node using Devel module I can see that the 'field_paystub_upload' array is null. So for some reason its doing everything right except attaching the file to the node and that is what I've been banging my head on for days. Best response gets on free internet?
Drupal's file.inc file_save_upload uses $_FILES, which is a global, magically set by PHP. Drupal expects an uploaded file, not a file that exists locally.
You best just call a custom file-saver method, to process local files. Make sure its path up in the files database-table too. file_save_upload will be valuable for creating such a helper method.
Big thanks to berkes for helping me solve this problem. Turns out that since the files were already on the drupal webserver and not being uploaded to PHP $_FILES global variable, I was unable to programmatically upload the file correctly.
This was causing every other way I've tried to fail. I tried using Drupals defualt upload module and I also tried using CCK's fielfield module both were not working. Thanks to berkes suggestion I found a function that comes with CCK's filefield widget to save uploaded files that are already on the server. Hopefully this helps someone else.
This is the function I found that can save a file thats already on the web-server.
Here is the working code I used to create the node and attach the file after calling field_file_save_file.
function create_drupal_node($employeeID, $employeeDate, $drupalUid, $file2){
$file_remove_html_extention = substr($file2, 0, -7);
$file_pdf = $file_remove_html_extention . '.pdf';
$node = new stdClass();
$node->type = 'paystub';
$node->status = 1;
$node->uid = $drupalUid;
$node->title = $employeeDate . ' - eStub';
$node->body = $employeeID;
$node->created = time();
$node->changed = $node->created;
$node->promote = 1;
$node->sticky = 0;
$node->format = 1;
$node->language = 'en';
$file = '/var/www/html/mgldev.foobar.com/burst_pdfs/pdfs/' . $file_pdf;
// Get the path to your Drupal site's files directory
$dest_folder = '/paystubs/' . $drupalUid;
$dest = 'paystubs/' . $drupalUid . '/' . $file_pdf;
if (!file_check_directory($dest_folder, TRUE)){
mkdir($dest_folder);
}
// Load the CCK field
$field = content_fields('field_paystub_upload', 'paystub');
// Load the appropriate validators
$validators = array_merge(filefield_widget_upload_validators($field));
// Create the file object
$file = field_file_save_file($file, $validators, $dest_folder);
// Apply the file to the field, this sets the first file only, could be looped
// if there were more files
$node->field_paystub_upload = array(0 => $file);
// The file has been copied in the appropriate directory, so it can be
// removed from the import directory
unlink($file);
// change file status to permanent
file_set_status($file,1);
node_save($node);
}
</pre></code>
Thanks again berkes