Image upload still submitting with callback validation in CI - php

I am trying to do a image upload validation on codeigniter 3. I have tried many tut's but still face this issue. I would like if the user was to leave the upload a photo area blank ( eventually if they upload a unsupported mime and size) for it to throw a error before it allows or tries to submit the data.
Right now it throws a error but showing the database query along with "Image in sql cannot be blank". I would like it to show like a regular form validation would without it showing the sql query and error.
It still seems to submit the form without it throwing the error first, because it says $post_image undefined.
I have already tried entering a callback with isset function to try to only allow the form to submit data if a image was uploaded, if not I was trying to display the errors by passing the error variable. None of this seems to work correctly as I explained above.
Controller:
public function create(){
//Check in login session
if(!$this->session->userdata('logged_in')){
$this->session->set_flashdata('log_post','Please login or create a free account to post a ad.');
redirect('users/register');
}
$data['title'] = 'Create a Post';
$data['categories'] = $this->post_model->get_categories();
$data['states'] = $this->post_model->get_city();
$this->form_validation->set_error_delimiters('<div class="error"> <h7> Error: </h7>', '</div>');
$this->form_validation->set_rules('title','Title',array('required', 'min_length[3]'));
//$this->form_validation->set_rules('file','Image Upload','required');
$this->form_validation->set_rules('Description','About You',array('required', 'min_length[5]'));
$this->form_validation->set_rules('Number','Phone Number',array('required', 'min_length[7]'));
$this->form_validation->set_rules('Area','Location/Area',array('required', 'min_length[2]'));
if($this->form_validation->run() === FALSE){
$this->load->view('templates/header');
$this->load->view('posts/create', $data);
$this->load->view('templates/footer');
} else {
// $this->load->helper('file');
//$this->form_validation->set_rules('file','','callback_file_check');
if($this->form_validation->run()==TRUE){
$config['upload_path'] = 'assets/images/posts';
$config['allowed_types'] = 'jpg|jpeg|png';
$config['encrypt_name'] = TRUE; //TURN ON
$config['max_size'] = 0;
$config['max_width'] = 0;
$config['max_height'] = 0;
$this->upload->initialize($config);
if(!$this->upload->do_upload('file')){
$errors = array('error'=>$this->upload->display_errors());
$this->load->view('templates/header');
$this->load->view('posts/create', $errors);
$this->load->view('templates/footer');
}else {
$data = $this->upload->data();
$post_image = $data['file_name'];
}
}
$this->post_model->create_post($post_image);
$this->session->set_flashdata('post_created','Your Post has been submitted');
redirect('posts');
}
}
}// end of class
Model:
public function create_post($post_image){
$slug = md5(uniqid().mt_rand());
//url_title($this->input->post('title'), 'dash', TRUE). // this is the orginal way for slug SEO friendly
$site = $this->input->post('site');
//adds HTTP too website links
if (!preg_match("~^(?:f|ht)tps?://~i", $site)) {
$site = "http://" . $site;
}
$data = array(
'title'=>$this->input->post('title'),
'body'=> $this->input->post('Description'),
'post_image' => $post_image
);
return $this->db->insert('posts',$data);
}
View:
<div class="form-group row">
<label class="col-sm-3 col-form-label" for="textarea">Photo</label>
<div class="col-lg-8">
<div class="mb10">
<?php echo form_error('file') ?>
<input name="file" type="file" class="form-control-file" id="exampleInputFile" aria-describedby="fileHelp">
</div>
<?php if (isset($error)) { echo $error; } ?>
</div>

Related

How can I store validation errors related to image upload as flash massages in this Codeigniter 3 application?

I am working on a basic blog application with Codeigniter 3.1.8 and Bootstrap 4.
The posts, of course, have main images. There is a default image if no image is uploaded by the user.
There are restrictions on image files a user can upload:
$config['upload_path'] = './assets/img/posts';
$config['allowed_types'] = 'jpg|jpeg|png';
$config['max_size'] = '2048';
I have managed to display the upload error messages that correspond to the configuration above (for your curiosity and/or use, the code is here).
For the update() method however, since there are redirects involved, all form validation messages are stored as "flash messages".
public function update() {
// Form data validation rules
$this->form_validation->set_rules('title', 'Title', 'required', array('required' => 'The %s field can not be empty'));
$this->form_validation->set_rules('desc', 'Short description', 'required', array('required' => 'The %s field can not be empty'));
$this->form_validation->set_rules('body', 'Body', 'required', array('required' => 'The %s field can not be empty'));
$this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');
$id = $this->input->post('id');
// Update slug (from title)
if ($this->form_validation->run()) {
$slug = url_title(convert_accented_characters($this->input->post('title')), 'dash', TRUE);
$slugcount = $this->Posts_model->slug_count($slug, $id);
if ($slugcount > 0) {
$slug = $slug."-".$slugcount;
}
} else {
$slug = $this->input->post('slug');
}
// Upload image
$config['upload_path'] = './assets/img/posts';
$config['allowed_types'] = 'jpg|jpeg|png';
$config['max_size'] = '2048';
$this->load->library('upload', $config);
if (isset($_FILES['userfile']['name']) && $_FILES['userfile']['name'] != null) {
// Use name field in do_upload method
if (!$this->upload->do_upload('userfile')) {
$errors = array('error' => $this->upload->display_errors());
// Dysplay upload validation errors
// only if a file is uploaded and there are errors
if (empty($_FILES['userfile']['name'])) {
$errors = [];
}
if (!empty($errors)) {
$data['upload_errors'] = $errors;
}
} else {
$data = $this->upload->data();
$post_image = $data[ 'raw_name'].$data[ 'file_ext'];
}
}
else {
$post_image = $this->input->post('postimage');
}
if ($this->form_validation->run() && empty($errors)) {
$this->Posts_model->update_post($id, $post_image, $slug);
$this->session->set_flashdata('post_updated', 'Your post has been updated');
redirect('/' . $slug);
} else {
$this->form_validation->run();
$this->session->set_flashdata('errors', validation_errors());
// this line was added later
// but the bug persists
$this->session->set_flashdata('upload_errors', $errors);
redirect('/dashboard/posts/edit/' . $slug);
}
}
In the edit-post.php view I have:
<input type="hidden" name="postimage" id="postimage" value="<?php echo $post->post_image; ?>">
<label for="postimage">Upload an image</label>
<div class="form-group">
<input type="file" name="userfile" id="postimage" size="20">
<?php if ($this->session->flashdata('upload_errors')) { ?>
<div class="error-messages">
<?php if(isset($upload_errors)){
foreach ($upload_errors as $upload_error) {
echo $upload_error;
}
}?>
</div>
<?php } ?>
</div>
I have not been able to add the image upload errors messages as "flash messages".
How can I do that?
In edit-post.php you have to change:
<?php if ($this->session->flashdata('upload_errors')) { ?>
With:
<?php if ($upload_errors = $this->session->flashdata('upload_errors')) { ?>
Try this:
$this->session->set_flashdata('errors', validation_errors());
$this->session->set_flashdata('upload_errors', $errors);
Or you can create an $errorArray from validation_errors() and $errors.
I do the exact same thing (upload errors go into a flashdata element). Here's how it works for me:
(I'll skip the upload config... but for this example, it's stored in an array conveniently named $config)
In my controller:
$this->load->library('upload', $config);
if (!$this->upload->do_upload('userfile'))
{
$this->session->set_flashdata('message', "An error ocurred: ".$this->upload->display_errors());
$this->session->set_flashdata('alert_class', "alert-danger");
}
else
{
$this->session->set_flashdata('message', "Upload successful");
$this->session->set_flashdata('alert_class', "alert-success");
}
In my view (all my views carry this code)
<?php
if (null !== $this->session->flashdata('message'))
{ ?>
<div class="alert <?php echo $this->session->flashdata('alert_class'); ?> text-center mb-2"><i class="fas fa-exclamation-triangle fa-fw"></i> <?php echo $this->session->flashdata('message'); ?></div>
<?php
}
?>
In this way, if I don't set a flashdata element called message the view won't even display the DIV where alert is displayed. If, on the other hand, I do set the message element, a col-12 alert is displayed with the message I defined and styled with the alert class I want (success, warning, danger, info, etc)
This will only work for upload validation errors. In your multipart form you may also have regular validation errors which you should check for separately. You can do the same with a flash element:
$this->session->set_flashdata('message', validation_errors());
I use the same element name (message) because I'd stop upon the first error, So there would be no upload error and form validation error in the same display.
This should work.
public function update()
{
// Form data validation rules
$this->form_validation->set_rules('title', 'Title', 'required', array('required' => 'The %s field can not be empty'));
$this->form_validation->set_rules('desc', 'Short description', 'required', array('required' => 'The %s field can not be empty'));
$this->form_validation->set_rules('body', 'Body', 'required', array('required' => 'The %s field can not be empty'));
$this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');
$id = $this->input->post('id');
$form_is_valid = $this->form_validation->run()
$errors = [];
// Update slug (from title)
if ($form_is_valid) {
$slug = url_title(convert_accented_characters($this->input->post('title')), 'dash', TRUE);
$slugcount = $this->Posts_model->slug_count($slug, $id);
if ($slugcount > 0) {
$slug = $slug."-".$slugcount;
}
} else {
$slug = $this->input->post('slug');
$errors[] = validation_errors();
}
// Upload image
$config['upload_path'] = './assets/img/posts';
$config['allowed_types'] = 'jpg|jpeg|png';
$config['max_size'] = '2048';
$this->load->library('upload', $config);
if (isset($_FILES['userfile']['name']) && $_FILES['userfile']['name'] != null) {
// Use name field in do_upload method
if (!$this->upload->do_upload('userfile')) {
$upload_errors = array('error' => $this->upload->display_errors());
// Dysplay upload validation errors
// only if a file is uploaded and there are errors
if (empty($_FILES['userfile']['name'])) {
$upload_errors = [];
}
if (!empty($upload_errors)) {
$data['upload_errors'] = $upload_errors;
$errors[] = $upload_errors;
}
} else {
$data = $this->upload->data();
$post_image = $data[ 'raw_name'].$data[ 'file_ext'];
}
}
else {
$post_image = $this->input->post('postimage');
}
if (empty($errors)) {
$this->Posts_model->update_post($id, $post_image, $slug);
$this->session->set_flashdata('post_updated', 'Your post has been updated');
redirect('/' . $slug);
} else {
$this->session->set_flashdata('errors', $errors);
redirect('/dashboard/posts/edit/' . $slug);
}
}
$this->form_vlaidation->run() is called only once.
Errors are saved both (form validation & upload) in the same array.
Post is updated only if $errors is empty.
You should think how you can improve the code further.
Try this one .Add this in constructor
$this->session->keep_flashdata('errors');
and remove session data after use it in view
$this->session->unset_userdata('errors');

Codeigniter : I am trying to submit form either if user chooses any image to upload or not choose. is it possible?

Right now, submit form works good when i am choosing image to upload . But i am trying to submit same form even if not choosing any image...
controller
function create(){
$this->data['categories'] = $this->News_model->getNewsCategories();
$this->data['status'] = $this->status;
if($this->input->post()){
$title =$this->input->post('title');
$slug =$this->input->post('slug');
$desc =$this->input->post('desc');
$category_id =$this->input->post('category');
$upload_path = FCPATH.'assets/uploads/news';
$field_name ='image';
$temp_file_name = $this->file[$field_name]['name'];
$file_name = time().'_'.$this->randomString(10).'.'.$this->getFileExtension($temp_file_name);
if(!$this->uploadImage($upload_path,$file_name,$field_name)){
$this->session->set_flashdata('error', $this->file_error);
}
else{
$this->createThumbnail($this->file_data['full_path'], $upload_path.'/thumb/'.$file_name,75,50);
if(!$this->News_model->insertNews($title,$slug,$desc,$category_id,$file_name)){
$this->session->set_flashdata('error', 'Record couldn\'n inserted. Please try again.');
}
else{
$this->session->set_flashdata('success', 'News created.');
redirect('admin/news');
}
}
}
$this->load->view('admin/template/header');
$this->load->view('admin/news/create',$this->data);
$this->load->view('admin/template/footer');
}
if some one have idea to submit form for both the case, then help me to short-out this problem. thanks.....
try this code just put one if condition on file name is not empty
function create(){
$this->data['categories'] = $this->News_model->getNewsCategories();
$this->data['status'] = $this->status;
if($this->input->post()){
$title =$this->input->post('title');
$slug =$this->input->post('slug');
$desc =$this->input->post('desc');
$category_id =$this->input->post('category');
$file_name = $_FILES['image']['name'];
if(!empty($file_name)){
$upload_path = FCPATH.'assets/uploads/news';
$field_name ='image';
$temp_file_name = $this->file[$field_name]['name'];
$file_name = time().'_'.$this->randomString(10).'.'.$this->getFileExtension($temp_file_name);
if(!$this->uploadImage($upload_path,$file_name,$field_name)){
$this->session->set_flashdata('error', $this->file_error);
}
else{
$this->createThumbnail($this->file_data['full_path'], $upload_path.'/thumb/'.$file_name,75,50);
}
}
if(!$this->News_model->insertNews($title,$slug,$desc,$category_id,$file_name)){
$this->session->set_flashdata('error', 'Record couldn\'n inserted. Please try again.');
}
else{
$this->session->set_flashdata('success', 'News created.');
redirect('admin/news');
}
}
$this->load->view('admin/template/header');
$this->load->view('admin/news/create',$this->data);
$this->load->view('admin/template/footer');
}
You can check file have uploaded or not by this:
if (isset($_FILES['upload_field_name']) && is_uploaded_file($_FILES['upload_field_name']['tmp_name'])) {
//load upload class with the config, etc...
$this->load->library('upload', $config);
}

codeigniter alert if image size exceeds

Hi I have this code for uploading an image. I can perfectly add the image but I want to add restrictions and there will an alert that will pop up if image size exceeds but I don't know how can add I alert if image size exceeds. please help me
Here's my code:
CONTROLLERS:
public function upload_file()
{
$filename = 'r_image';
$status = "";
$msg = "";
$config['upload_path'] = 'img/recipes/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = 1024 * 8 ;
$config['encrypt_name'] = true;
$this->load->library('upload',$config);
if (!$this->upload->do_upload($filename))
{
$stats = 'error';
$msg = $this->upload->display_errors('', '');
}else{
$uploadData = $this->upload->data('file_name');
if($uploadData['file_name'])
{
$thumnail = 'img/recipes/'.$uploadData['file_name'];
}else{
$thumnail = 'No thumnbail uploaded!';
}
$updateThumbData = array('recipe_id' => $recipe_id,
'r_image' => $thumnail
);
$this->products_model->updataRecipeThumnail($updateThumbData);
redirect('dashboard/view_product');
} /* upload_file() */
}
for uploading files you must use POST method. read this w3schools file upload.
if($_FILES['Your_POST_name']['size']>1024 * 8 )// to check what is your post name print_r($_FILES);
{
$this->session->set_flashdata('msg', '<div class="alert alert-danger alert-dismissible fade in" role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>Image is too big!</div>');
redirect('dashboard/view_product');
}
and in your view_product's view file, add following code to display error
<?php echo $this->session->flashdata('msg'); ?>
Important things to remember while dealing with file uploads in php.
Make sure that the form uses method="post"
The form also needs the following attribute:
enctype="multipart/form-data". It specifies which content-type to use
when submitting the form
Without the requirements above, the file upload will not work.

Upload two files in codeIgniter showing error

my View form multipart
<h3>Upload Submission File(doc,docx,pdf,cda,rtf,txt)</h3>
<?php echo form_error('fileToUpload'); ?>
<p>
<input type="file" name="fileToUpload" id="fileToUpload" title="Upload Submission File"
accept="application/pdf, .doc, .docx, .txt, application/msword, .rtf, .cda"/>
</p>
<h3>Upload Additional File (gif,jpeg,png,tiff,pdf)</h3>
<?php echo form_error('additionalUpload'); ?>
<p>
<input type="file" name="additionalUpload" id="additionalUpload" title="Upload Additional File"
accept="image/gif, image/jpeg, image/png, image/x-tiff, application/pdf" />
</p>
My Contoller
function submit_article() {
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_error_delimiters('<p style="color:red">', '<br/></p>');
$my_rules = array(
array(
'field' => 'fileToUpload',
'label' => 'Submission File',
'rules' => 'callback_is_proper_file'
),
array(
'field' => 'additionalUpload',
'label' => 'Additional File',
'rules' => 'callback_is_image'
)
);
$this->form_validation->set_rules($my_rules);
if ($this->form_validation->run() == FALSE) {
//ERROR
$data['title'] = ucfirst('submit Article');
$this->load->view('templates/header', $data);
$this->load->view('submit_article', $data);
$this->load->view('templates/footer', $data);
} else {
//SUCCESS
$data['title'] = ucfirst('article Submitted');
$this->load->view('templates/header', $data);
$this->load->view('forms_view/submit_article_success', $data);
$this->load->view('templates/footer', $data);
}
}
function is_image() {
if ($_FILES['additionalUpload']['tmp_name'] != '') {
$config1['upload_path'] = './public/uploads/';
$config1['allowed_types'] = 'gif|jpg|jpeg|png|pdf|tiff';
$config1['max_size'] = '2048';
$config1['max_width'] = '0';
$config1['max_height'] = '0';
$config1['remove_spaces'] = true;
$config1['overwrite'] = true;
$this->load->library('upload', $config1);
if (!$this->upload->do_upload('additionalUpload')) {
$this->form_validation->set_message('is_image', $this->upload->display_errors('<p style="color:red">', '<br/></p>'));
return FALSE;
} else {
$this->upload->data();
return TRUE;
}
}
}
function is_proper_file() {
if ($_FILES['fileToUpload']['tmp_name'] != '') {
$config['upload_path'] = './public/uploads/';
$config['allowed_types'] = 'doc|docx|pdf|cda|rtf|txt';
$config['max_size'] = '1024*10';
$config['max_width'] = '0';
$config['max_height'] = '0';
$config['remove_spaces'] = true;
$config['overwrite'] = true;
$this->load->library('upload', $config);
if (!$this->upload->do_upload('fileToUpload')) {
$this->form_validation->set_message('is_proper_file', $this->upload->display_errors('<p style="color:red">', '<br/></p>'));
return FALSE;
} else {
$this->upload->data();
return TRUE;
}
} else {
$this->form_validation->set_message('is_proper_file', '<p style="color:red">Please select a file to upload.<br/></p>');
return FALSE;
}
}
The additionalUpload field is not required field and filetoupload is a required field.
when i submit the form by filling all the details except additionalUpload my code works well for me, but when i submit the form with additionalUpload along with aal other details it shows me error "The filetype you are attempting to upload is not allowed." for additionalUpload field..
in other words when i submit the form with one file that is filetoupload which is required its works for me.. and when i submit the form with both the files that is filetoUpload and additionalUpload then its shows me error for the additional upload fields "The filetype you are attempting to upload is not allowed.",, and when i simply submit the form with only addtionalupload file its do the upload in my upload folder but when i submit with all the fields it shows me error "The filetype you are attempting to upload is not allowed." for the additional Upload filed..
THANKS IN ADVANCE PLEASE HELP ANYONE
$this->load->library('upload');
$this->upload->initialize($config1);
I need to call it like above where as I have called it in this way:
$this->load->library('upload',$config);

How to make codeigniter sticky form when error comes from upload file field

I have a form that allows user to upload multiple files. Additionaly user have to fill other input text fields like address, email etc.
I don't know how to make form sticky if error comes from file uploading and how to access error messages set by form_validation library. Because if for example one of the filetype is not allowed I use redirect to step out of the loop responsible for uploading every file.
To keep upload error message I use $this->session->set_flashdata('errors', $errors) but then I'm not able to use error messages from form_validation library ( echo form_error('field_name) ) and display user input in form fields ( echo set_value('field_name'))
Here is controller method responsible for file upload and data insert:
function do_upload()
{
// load form validation library
$this->load->library('form_validation');
// set validation rules
$this->form_validation->set_rules('email','Email','trim|required|valid_email|matches[confirm_email]');
$this->form_validation->set_rules('confirm_email','Email','trim|required|valid_email');
$this->form_validation->set_rules('delivery_name','Nazwa','trim|required');
$this->form_validation->set_rules('delivery_street','Ulica','trim|required');
$this->form_validation->set_rules('delivery_city','Miasto','trim|required');
$this->form_validation->set_rules('delivery_postcode','Kod pocztowy','trim|required');
$this->form_validation->set_rules('delivery_country','Kraj','trim|required');
$this->form_validation->set_rules('captcha','Captcha','callback_check_captcha');
if ( $this->form_validation->run() )
{
// if validation passes I insert form data into database and I start to upload
// all the files using foreach loop
$config['upload_path'] = './uploads/upload_directory';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '0';
$upload_data = array();
$task_address_id_array = $this->MTasks->insertNewTask($task_directory);
$task_id = $task_address_id_array['task_id'];
$address_id = $task_address_id_array['address_id'];
// iterate over files to be uploaded
foreach ($_FILES as $key => $value)
{
if (!empty($value['name']))
{
$this->upload->initialize($config);
$result = $this->upload->do_upload($key);
if (!$result)
{
// if upload error occurs I need to redirect to break the loop
$errors = $this->upload->display_errors();
$this->session->set_flashdata('errors', $errors);
redirect();
}
else
{
$current_upload_data = $this->upload->data();
// insert upload data to database
$this->MTasks->insertFileInfo($current_upload_data,$task_id);
}
}
}
redirect('upload/success_message');
}
else
{
$this->load->view('include/header');
$this->load->view('upload_form',$this->data);
$this->load->view('include/footer');
}
}
The main problem is you can not put as validation rule file uploads, because the library executes one by one.
A simple solution is to validate your fields and then validate the file upload. Example:
<?php
function save()
{
$this->load->library('form_validation');
$this->form_validation->set_rules('name', 'Name', 'trim|required');
if($this->form_validation->run() == FALSE)
{
$this->form_validation->set_error_delimiters('', '<br />');
echo validation_errors();
exit();
}
else
{
if($_FILES['imagen']['error'] != 4)
{
$image $this->_manage_image($this->input->post('name'));
}
else
{
exit('No empty field!');
}
# save in your bd o success message...
}
}
function _manage_image($name)
{
# config
$config['upload_path'] = './images/products/';
$config['allowed_types'] = 'gif|jpg|png';
// ...
$config['file_name'] = $name;
$this->load->library('upload', $config);
if (!$this->upload->do_upload('image'))
{
# errors...
echo $this->upload->display_errors();
exit();
}
else
{
# upload
return $img_data['file_name'];
}
}

Categories