Attachement file deletion after sending out an email - php

In a larger project, have a form which uploads 2 files. I am using codeigniter as the framework. After the form upload it should send these 2 files as an email.
In order to attach it to an email, we should have a local copy of the file. Hence I move the files to a temporary folder and use the naming convention of [session-id]_my_file_1 and [session-id]_my_file_2
Finally after sending out the email I try to delete the these temporary files. But unlink is not deleting these files. I donot know the reason for this.
My guess is: It may be still being used by the mail command to upload/send. Below are the code outline I have written.
$config['upload_path'] = './tmp_holder/';
$config['allowed_types'] = 'doc|docx|pdf|rtf';
$config['max_size'] = '10240';
$config['file_name'] = $this->session->userdata('session_id').'_1';
$config['overwrite'] = TRUE;
$config2['upload_path'] = './tmp_holder/';
$config2['allowed_types'] = 'doc|docx|pdf|rtf';
$config2['max_size'] = '10240';
$config2['file_name'] = $this->session->userdata('session_id').'_2';
$config2['overwrite'] = TRUE;
$this->load->library('upload',$config);
if ($this->form_validation->run() == FALSE)
{
$this->load->view('init_app_form');
}
else
{
if($this->upload->do_upload('cvFile') === FALSE) {
$this->load->view('init_app_form');
}
else {
$file1Return = $this->upload->data();
$this->upload->initialize($config2);
if($this->upload->do_upload('researchFile') === FALSE) {
$this->load->view('init_app_form');
}
else {
//process data here
$file2Return = $this->upload->data();
$this->config->load('email');
$this->email->initialize($this->config->item('email_conf'));
$this->email->from($this->config->item('email_from'), $this->input->post('tname').' '.$this->input->post('fname').' '.$this->input->post('lname'));
$this->email->to($this->config->item('email_to'));
$this->email->subject('something');
$this->email->message('something');
$this->email->attach($file1Return['full_path']);
$this->email->attach($file2Return['full_path']);
if( $this->email->send() == false ) {
//error
echo $this->email->print_debugger(); exit;
}
$this->email->clear();
////////////////////////////////
#unlink($this->session->userdata('session_id').'_2');
////////////////////////////////
$this->load->view('init_app_success');
}
////////////////////////////////
#unlink($this->session->userdata('session_id').'_1');
////////////////////////////////
}
}
The Solution I did was to delete the files in the temp folder before I do this so that previous files are cleared. But this is not a clean approach right? This is because:
It may be trying deleting other files currently being used by other parallel instances
I want the tmp folder to be empty after I send itself.

Its better to use file_helper which is in code igniter.
$this->load->helper("file");
delete_files($this->session->userdata('session_id').'_1');
here is documentation for this

Related

CodeIgniter Upload Class file_ext_tolower not working, even on localhost

I have a really weird problem. I'm using the CodeIgniter Upload Class for managing the upload of a simple jpg image. If I upload a file with extension .JPG, even if I set the property file_ext_tolower to TRUE, my file gets uploaded with the .JPG extension. Which is something that I don't want! Here is some code..
$this->load->library('upload');
$config['upload_path'] = './resources/img/content';
$config['allowed_types'] = 'jpg';
$config['overwrite'] = FALSE;
$config['file_ext_tolower'] = TRUE;
$config['remove_spaces'] = TRUE;
$this->upload->initialize($config, true);
if ( ! $this->upload->do_upload('cover')) {
$this->session->set_flashdata('message','Cover: ' . $this->upload->display_errors());
redirect('admin');
break;
} else {
// Whatever
}
Problem is, this doesn't run even on localhost. It always goes ahead and uploads the file with the .JPG. I just cannot understand. I'm using CodeIgniter 3.1.0 on both the server and the localhost. Any thoughts? On the server I've also enabled the fileinfo extension in the php.ini.
Another thing that this brings is that..if I have a file named myfile.JPG and myfile.jpg, CodeIgniter isn't able to see that they're the same file..which is ultimately what would be likely it does if only file_ext_tolower was working properly.
On server, myfile.JPG gets saved as myfile.JPG. I think that, when file_ext_tolower is set to TRUE, it should save as myfile.jpg...and eventually, before doing that, actually search for another file with this name..if file with this name is already on the server, it should follow the overwrite setting: either overwrite it or rename with a progressive number.
I have solution for you :)
Create file: application/libraries/MY_Upload.php
<?php
class MY_Upload extends CI_Upload
{
/**
* Force filename to lowercase
*
* #var string
*/
public $file_name_tolower = FALSE;
function _prep_filename($filename)
{
if ($this->mod_mime_fix === FALSE OR $this->allowed_types === '*' OR ($ext_pos = strrpos($filename, '.')) === FALSE)
{
return $filename;
}
$ext = substr($filename, $ext_pos);
$filename = substr($filename, 0, $ext_pos);
//change ext tolower
$filename = ($this->file_name_tolower)?strtolower($filename):$filename;
//change ext tolower
$ext = ($this->file_ext_tolower)?strtolower($ext):$ext;
return str_replace('.', '_', $filename).$ext;
}
}
I modyfication file_ext_tolower and add file_name_tolower
Example for file: coVEr.JPG
...
$config['file_ext_tolower'] = TRUE;
$config['file_name_tolower'] = TRUE;
...
Result: cover.jpg
...
$config['file_ext_tolower'] = TRUE;
$config['file_name_tolower'] = FALSE;
...
Result: coVEr.jpg
...
$config['file_ext_tolower'] = FALSE;
$config['file_name_tolower'] = TRUE;
...
Result: cover.JPG
...
$config['file_ext_tolower'] = FALSE;
$config['file_name_tolower'] = FALSE;
...
Result: coVEr.JPG
I have the same problem. It is silly mistake, no matter how much code i edit on this file also no effect on result. So I start guess I refer to wrong file :
maybe member-site file but I edit admin-site file.
maybe order-model file but I edit invoice-model file.
After echo "alert("abc");" to find the correct file, then i edit the code then finally I get the result output perfectly.

how to fix unwanted double copy of uploaded file?

My code is running fine and adding the files correctly but it is adding one additional copy of uploaded file. What is wrong?
My controller is like this:
public function add_audio(){
$config['upload_path'] = './musics/';
$config['allowed_types'] = 'mp3';
$config['max_size'] = '999999999999999999999';
$this->load->library('upload',$config);
$this->upload->do_upload();
if ( ! $this->upload->do_upload())
{
$data['error'] = $this->upload->display_errors();
print_r($data['error']);
//line of codes that displays if there are errors
}
else
{
$data['audio'] = $_FILES['userfile']['name'];
$this->load->model('main');
$query = $this->main->insert('audio',$data);
if($query == TRUE){
$this->load->view('admin/success');
}
}
... but it is adding one additional copy of uploaded file. What is wrong?
That's because you're calling do_upload() twice...
public function add_audio()
{
....
$this->upload->do_upload(); // <- FIRST upload (remove this one)
if ( ! $this->upload->do_upload() ) // <- SECOND upload
{
....
Since you may need the conditional logic that handles upload failures, delete the first instance of do_upload().

Codeigniter Multiple File Upload Encryption Issue

I've got a big form that allows users to upload multiple files/filetypes to an offer/bid they are creating. Everything is working fine except one piece: the name encryption of the files before saving to the database.
I haven't found a rhyme or reason for it, but it's hit or miss. The image works fine every time. The other documents (which allow all [*] types, but primarily will consist of various business docs such as pdf, doc, xls, etc.) are the ones that are spotty.
I found threads on SO and elsewhere about general issues with the name encryption but have yet to come across one that deals with the specificity of my issue.
Here's the upload function:
//for multi uploads
function do_uploads($name, $file)
{
$status ="";
$msg = "";
$file_element_name = $name;
//go through and figure out where it goes
if($name == "QuoteDoc") {
$folder = "quotedocs";
$allowed = '*';
}
else if($name == "ProductOfferPhoto") {
$folder = "product_photos";
$allowed = 'jpeg|jpg|png|gif';
}
else if($name == "ResearchWhtPaper1" || $name == "ResearchWhtPaper2") {
$folder = "research";
$allowed = "*";
}
else if($name == "ProductLiterature1" || $name == "ProductLiterature2") {
$folder = "literature";
$allowed = "*";
}
else if ($name == "FDALink") {
$folder = "fda";
$allowed = "*";
}
$config['upload_path'] = './uploads/' . $folder;
$config['allowed_types'] = $allowed;
$config['max_size'] = 1024 * 8;
$config['encrypt_name'] = TRUE;
$this->load->library('upload', $config);
if ( ! $this->upload->do_upload($name))
{
$status = 'error';
$msg = $this->upload->display_errors('', '');
}
else {
$data = $this->upload->data();
}
#unlink($_FILES[$file_element_name]);
//what's up?
//return $this->upload->data();
return array('status' => $status, 'msg' => $msg, 'data' => $this->upload->data(), 'allowed'=>$allowed);
}
Any help would be greatly appreciated.
You're not stating your question very clearly:
Are the names simply not being encrypted, but still uploading to the correct directories?
Are you setting these inside a loop, where perhaps the class instance is not being re-initialized? Does the first file encrypt correctly, but not the subsequent ones?
Can you track which file types are not working correctly?
I have trouble believing it is completely "random", and think there's just not enough research being done here
Solution from below:
You need to use $this->upload->initialize($config) to change the config, as the library will only be loaded once

data not setting in session codeigniter

//uploading product movie or image?
if($this->input->post('upload_360') == "Upload") {
$config['upload_path'] = './media/images/products/360s';
$config['allowed_types'] = 'swf';
$this->load->library('upload', $config);
$this->upload->initialize($config);
if (!$this->upload->do_upload('film')) {
$this->data['product_error'] = $this->upload->display_errors();
$this->template->build('/admin/products/create', $this->data);
} else {
$this->data['data_360'] = $this->upload->data();
$this->session->set_userdata(array('360_film' => $this->data['data_360']));
$this->template->build('/admin/products/create', $this->data);
}
$this->session->set_userdata(array('advantages' => $this->input->post('product_advantages')));
$this->data['session_advantages'] = $this->session->userdata('advantages');
}
//upload the product image, if successful the user will be
//notified if the image is too high or wide, and will be offered,
//the chance to crop the image. All cropping takes place in the media
//controller.
if($this->input->post('product_image') == "Upload") {
$config['upload_path'] = './media/images/products/';
$config['allowed_types'] = 'gif|jpg|jpeg|png';
$this->load->library('upload', $config);
$this->upload->initialize($config);
if (!$this->upload->do_upload('image_upload')) {
//die("!");
$this->data['image_error'] = $this->upload->display_errors();
$this->template->build('/admin/products/create', $this->data);
} else {
$this->data['image_data'] = $this->upload->data();
$this->session->set_userdata(array('image' => $this->data['image_data']));
$this->data['session_image'] = $this->session->userdata('image');
$this->template->build('/admin/products/create', $this->data);
}
$this->session->set_userdata(array('advantages' => $this->input->post('product_advantages')));
$this->data['session_advantages'] = $this->session->userdata('advantages');
}
if($this->input->post('screenshot_upload') == "Upload") {
$config['upload_path'] = './media/images/products/360s/screenshots/';
$config['allowed_types'] = 'gif|jpg|jpeg|png';
$this->load->library('upload', $config);
$this->upload->initialize($config);
if (!$this->upload->do_upload('screenshot')) {
//die("!");
$this->data['screenshot_error'] = $this->upload->display_errors();
$this->template->build('/admin/products/create', $this->data);
} else {
$this->data['screenshot_data'] = $this->upload->data();
$this->session->set_userdata(array('screenshot' => $this->data['screenshot_data']));
$this->data['session_screenshot'] = $this->session->userdata('screenshot');
$this->template->build('/admin/products/create', $this->data);
}
$this->session->set_userdata(array('advantages' => $this->input->post('product_advantages')));
$this->data['session_advantages'] = $this->session->userdata('advantages');
}
On my form I have the user choose a file and the click an upload button dependent on which button is clicked the file gets uploaded and the upload data gets saved in a session.
The session is then used to get data from to save to a database, the upload_360 session works, the product_image session works fine but the screenshot_upload session only has data when with the if statement (3rd one in the code) if I try and acccess it outside of the code then that portion of the session is empty?
Is there a reason for this?
Why are you storing data in a session before inserting it into the db?
Cookies can only hold 4KB of data...
but the screenshot_upload session only has data when with the if statement (3rd one in the code) if I try and acccess it outside of the code then that portion of the session is empty?
I don't understand that part of your question. Do you mean it only has data when only using the 3rd if statement? i.e. when only trying to do screenshot_upload and not product_image or 360_upload`? If so, that might speak to the cookie size limit.
Instead of
$this->session->set_userdata(array('screenshot' => $this->data['screenshot_data']));
$this->data['session_screenshot'] = $this->session->userdata('screenshot');
why don't you
$this->uploads_model->insert_screenshot_data($this->data['screenshot_data']);//send screenshot upload_data to model to be inserted into db
$this->data['screenshot_data'] = $this->data['screenshot_data'];//if you want to pass screenshot upload_data to template/view
?
It looks like you are sending output to the user before setting the session (I'm inferring this from the $this->template->build, which is custom code.)
The session, like headers, cannot be modified after anything (ANYTHING) has been sent to output. This is because the session itself is sent in the header.

Check the file name in CodeIgniter file upload function

I'm using the following CodeIgniter function to upload files which works fine:
function uploadFiles(){
$this->load->library('upload');
$error = 0;
$projectName = $_POST['projectname'];
$projectID = $_POST['maxid'];
$folderName = $this->config->item('upload_dest')."/".$projectName."_".$projectID;
if(!file_exists ($folderName)){
$aa = mkdir($folderName);
}
$config['upload_path'] = $folderName;
$config['allowed_types'] = 'xml';
//$config['allowed_types'] = '*';
$config['max_size'] = '0';
$config['overwrite'] = TRUE;
$this->upload->initialize($config);
for($i=0; $i<count($_FILES['files']['name']); $i++)
{
$_FILES['userfile']['name'] = $_FILES['files']['name'][$i];
$_FILES['userfile']['type'] = $_FILES['files']['type'][$i];
$_FILES['userfile']['tmp_name'] = $_FILES['files']['tmp_name'][$i];
$_FILES['userfile']['error'] = $_FILES['files']['error'][$i];
$_FILES['userfile']['size'] = $_FILES['files']['size'][$i];
if($this->upload->do_upload())
{
$error += 0;
}else{
$error += 1;
}
}
if($error > 0){
$this->upload->display_errors();
return FALSE;
}
else{
return TRUE;
}
}
What I need to do is - check to make sure that at least one of the files which are being uploaded is named "etl". If there's no such a file in the file list the user chosen - stop the action, don't upload anything and return a form validation error. Could anybody advise over this?
Thanks.
Firstly, from php there is no way to get the name of the file(s) before uploading, you must upload to get the properties of the file. So, the options available are:
(1) Allow the files to be uploaded, then get the names and check if any contains "etl". If non contains what you are looking for, then delete the just uploaded files, and set a custom error message yourself.
This approach have a very large overhead cost of allowing you to first upload what is not need, then deleting it. Very poor but solves the problem.
(2) On the otherhand, is the javascript solution. Give the upload fields a common class name
e.g "userfile1", "userfile2", .......
then from your javascript and using jquery, intercept the submission of the form, then use a for loop to get the values of each of the file upload field, from which you can get the full name and extension of the file and then do your "etl" comparison.
i.e
<script type="text/javascript" >
$("#formname").submit(function(){
$(".classname").each(function(){
if($(this).val().indexOf("etl") != -1 ){
return true;
}
});
/*
*whatever makes it finish executing that loop and the execution of code gets
*to this point, then the string "etl" was not found in any of the names.
*/
// write a piece of code to show an hidden error field
$("#hidden_error_div").text("Your error message").show();
return false; //makes sure the form is not submitted.
});
</script>
Hope this helps.
Oyekunmi gives a good javascript solution to intercept before it actually gets to the server. As Oyekunmi points out, once it gets there, it gets there as a package, so you could then store and process it in a temporary directory, eval each file there and process accordingly.

Categories