Codeigniter two file upload, one mandatory and one optional - php

I am trying to upload two files with the help of codeigniter functions.
One of the file should be mandatory and one should be optional.
I am using the code below to upload those files but I cannot figure out the way to make one optional and one mandatory. I tried few modifications to the code below, but i bumped into many errors. I am new to codeigniter.
Even the code below for handling the uploads may not be appropriate but it is working.
$config['upload_path'] = 'uploads/';
$path=$config['upload_path'];
$config['allowed_types'] = '*';
$this->load->library('upload');
$i=0;
foreach ($_FILES as $key => $value)
{
if (!empty($key['name']))
{
$this->upload->initialize($config);
if (!$this->upload->do_upload($key))
{
$errors = $this->upload->display_errors();
$this->session->set_flashdata('error', $errors);
redirect(base_url().'upload', 'refresh');
}
else
{
$data = array('upload_data' => $this->upload->data());
$p[$i] = $this->upload->data();
}
}
$i++;
} //endforeach
if(empty($errors)){
//if there are no errors, write it into the database
$data = array('user_id'=>$this->session->userdata('id'),
'name'=>$this->input->post('name'),
'screenshot'=>$p[1]['file_name'],
'model'=> $p[0]['file_name'],
'created'=>date('Y-m-d H:i:s')
);
if($this->usermodel_model->save($data)){
//success
redirect(base_url().'dashboard?success');
}else{
//failed
redirect(base_url().'upload');
}
}

Sohanmax put $i++; inside if (!empty($key['name'])){ } and after ending foreach check if($i !=0) if it's false show the error, hope it'll work.

Related

Is there a better way of multipart/form-data validation

I have a multipart/form-data with an image upload and some personal data, so I want to include file upload in form validation, I can successfully do this.
However, I now find that there is an issue, ie even if my other form fields have errors and upload file field with no error, then image uploads to folder, how to prevent this, I mean, in my case, If name, email, file fields validation is ok then only file should upload, if name filed validation fails and file field validation ok then file should not upload
here is the code I use:
In Controller:
<?php
public $_rules = array(
'name'=>array('field'=>'name', 'label'=>'Name', 'rules'=>'trim|required'),
'email'=>array('field'=>'email', 'label'=>'Email', 'rules'=>'trim|required|valid_email'),
'profile_img'=>array('field'=>'profile_img', 'label'=>'Design', 'rules'=>'callback__profile_upload')
);
public function profile()
{
$this->load->library('upload');
$rules = $this->_rules;
$this->form_validation->set_rules($rules);
if($this->form_validation->run()==TRUE){
die('success');
}else {
$this->data['content'] = 'frontend/pages/place_order';
$this->load->view('frontend/_layout_main', $this->data);
}
}
function _profile_upload(){
if($_FILES['profile_img']['size'] != 0 && !empty($_FILES['profile_img']) ){
$upload_dir = './profile_pics/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir);
}
$config['upload_path'] = $upload_dir;
$config['allowed_types'] = 'gif|jpg|png|jpeg';
$config['file_name'] = 'profile_img_'.substr(md5(rand()),0,7);
$config['overwrite'] = false;
$config['max_size'] = '5120';
$this->upload->initialize($config);
if (!$this->upload->do_upload('profile_img')){
$this->form_validation->set_message('_profile_upload', $this->upload->display_errors());
return false;
}
else{
$this->upload_data['file'] = $this->upload->data();
return true;
}
}
else{
$this->form_validation->set_message('_profile_upload', "No file selected");
return false;
}
}
IN VIEW:
<?php echo form_open_multipart();?>
<?php $name_err = (!empty(form_error('name'))) ? 'err' : ' ';
echo form_input('name',set_value('name'), array('placeholder'=>'Name','class'=>" {$name_err } "));
?>
<?php $email_err = (!empty(form_error('email'))) ? 'err' : ' ';
echo form_input('email',set_value('email'), array('placeholder'=>'EMail','class'=>" {$email_err } "));
?>
<?php
echo form_error('profile_img');
echo form_upload(array('name' =>'profile_img', 'class' => 'inputfile inputfile-4', 'id' => 'profile_img'));
?>
<li><input type="submit" class="special" value="Submit" /></li>
Try once like this.I think for images not need to set rules like other fields.
public $_rules = array(
'name'=>array('field'=>'name', 'label'=>'Name', 'rules'=>'trim|required'),
'email'=>array('field'=>'email', 'label'=>'Email', 'rules'=>'trim|required|valid_email'),
);
And
public function profile()
{
$this->load->library('upload');
$rules = $this->_rules;
$this->form_validation->set_rules($rules);
if($this->form_validation->run()==TRUE){
die('success');
}else {
if ($this->_profile_upload()) { //return true if file uploaded successfully otherwise error
$this->data['content'] = 'frontend/pages/place_order';
$this->load->view('frontend/_layout_main', $this->data);
}
}
}
yes that is very obvious that your file get uploads even any other fields' validation failed. You have to initiate image uploading only after form validation success.
For that simply validate file specific requirement in that callback, and do actual uploads after successful form validation.
I have got a solution from codexWorld, I have asked same question over there, and they replied with a tutorial, If anybody still looking for a solution here is the link
http://www.codexworld.com/codeigniter-file-upload-validation/
in the validation call back, we just want to do the file type check
public function _profile_upload($str){
$allowed_mime_type_arr = array('image/jpeg','image/pjpeg','image/png','image/x-png');
$mime = get_mime_by_extension($_FILES['file']['name']);
if(isset($_FILES['file']['name']) && $_FILES['file']['name']!=""){
if(in_array($mime, $allowed_mime_type_arr)){
return true;
}else{
$this->form_validation->set_message('_profile_upload', 'Please select only pdf/gif/jpg/png file.');
return false;
}
}else{
$this->form_validation->set_message('_profile_upload', 'Please choose a file to upload.');
return false;
}
}
and in the main function we just want to do the same as normal, using do_upload and specifying the upload config items, anyhow there will be a second file type check when the function executes, I think that doesn't matter. The code will look like this::
public function profile()
{
$rules = $this->_rules;
$this->form_validation->set_rules($rules);
if($this->form_validation->run()==TRUE){
$config['upload_path'] = 'uploads/files/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = 1024;
$this->load->library('upload', $config);
//upload file to directory
if($this->upload->do_upload('file')){
$uploadData = $this->upload->data();
$uploadedFile = $uploadData['file_name'];
/*
*insert file information into the database
*.......
*/
}else{
$data['error_msg'] = $this->upload->display_errors();
}
}else {
$this->data['content'] = 'frontend/pages/place_order';
$this->load->view('frontend/_layout_main', $this->data);
}
}

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, uploading multiple files with same name

I have an upload form that allows me to add as many files as needed. However when I start trying to upload the files I get an error.
Controller
$this->load->library('upload');
$error = "";
$file = "";
$this->total_count_of_files = count($_FILES['user_certificates']['name']);
print_r($_FILES['user_certificates']['name']);
for($i=0; $i<$this->total_count_of_files; $i++)
{
$_FILES['user_certificates']['name'] = $_FILES['user_certificates']['name'][$i];
$_FILES['user_certificates']['type'] = $_FILES['user_certificates']['type'][$i];
$_FILES['user_certificates']['tmp_name'] = $_FILES['user_certificates']['tmp_name'][$i];
$_FILES['user_certificates']['error'] = $_FILES['user_certificates']['error'][$i];
$_FILES['user_certificates']['size'] = $_FILES['user_certificates']['size'][$i];
$config['encrypt_name'] = TRUE;
$config['file_name'] = $_FILES['user_certificates']['name'];
$config['upload_path'] = './certificate_files/';
$config['allowed_types'] = 'txt|pdf|doc|docx';
$config['max_size'] = 0;
$this->upload->initialize($config);
if (!$this->upload->do_upload())
{
$status = 'error';
$msg = $this->upload->display_errors();
}
else
{
$data = $this->upload->data();
$file = $data['raw_name'] . $data['file_ext'];
}
if($file)
{
$status = "success";
$msg = "Image successfully uploaded";
}
else
{
$status = "error";
$msg = "Something went wrong when saving the image, please try again.";
}
}
echo json_encode(array('status' => $status, 'msg' => $msg));
exit();
The print_r($_FILES['user_certificates']['name'])) shows me the files I have added:
Array ( [0] => license.txt [1] => license.txt )
I am totally stuck on how to get the upload to work. Any ideas?
Cheers in advance!
EDIT
If I change this:
if (!$this->upload->do_upload())
to this:
if (!$this->upload->do_upload('user_certificates'))
it works, but only for one file, it doesn't seem to loop round again for some reason
Your loops seems to be incorrect.
...
$_FILES['user_certificates']['name'] = $_FILES['user_certificates']['name'][$i];
...
these lines overwrite the original $_FILES array, so after completion of first loop, it will not find anything else in the loop because it got overwritten.
Instead you may first store the $_FILES array to a local variable and loop through it to upload one by one.

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

Check if a file is going to be uploaded? CodeIgniter

I have a form with few inputs and a file input.
I want to check whethere the file input is empty or not.
If it is empty do not try to upload, if it is not then try to upload it.
I tried something like this:
$upld_file = $this->upload->data();
if(!empty($upld_file))
{
//Upload file
}
you use codeigniter's file uploader class... and call $this->upload->do_upload(); in a conditional statement ahd check if its true.
<?php
if ( ! $this->upload->do_upload()){
$error = array('error' => $this->upload->display_errors());
$this->load->view('upload_form', $error);
}
else{
$data = array('upload_data' => $this->upload->data());
$this->load->view('upload_success', $data);
}
The user_guide explains this in detail: http://codeigniter.com/user_guide/libraries/file_uploading.html
However,
if you are dead set on checking whether a file has been "uploaded" aka.. submitted BEFORE you call this class (not sure why you would). You can access PHPs $_FILES super global.. and use a conditional to check if size is > 0.
http://www.php.net/manual/en/reserved.variables.files.php
Update 2: This is actual working code, i use it on an avatar uploader myself using CI 2.1
<?php
//Just in case you decide to use multiple file uploads for some reason..
//if not, take the code within the foreach statement
foreach($_FILES as $files => $filesValue){
if (!empty($filesValue['name'])){
if ( ! $this->upload->do_upload()){
$error = array('error' => $this->upload->display_errors());
$this->load->view('upload_form', $error);
}else{
$data = array('upload_data' => $this->upload->data());
$this->load->view('upload_success', $data);
}
}//nothing chosen, dont run.
}//end foreach
Probably do need more info. But basically, using the codeigniter upload class do something like this:
$result = $this->upload->do_upload();
if($result === FALSE)
{
// handle error
$message = $this->upload->display_errors();
}
else
{
// continue
}
There is a lot of functionality in codeigniter, probably don't need to re-invent the wheel here.

Categories