How to display disallowed file type error message in case of upload in Codeigniter 3?

大憨熊 提交于 2020-06-13 00:15:20

问题


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 but, if an image is uploaded, there are only 3 types allowed: jpg, jpeg and png.

Wanting to warn the user in case she/he tries to upload other file formats, I did this in the Posts controller:

// Upload image
$config['upload_path'] = './assets/img/posts';
$config['allowed_types'] = 'jpg|jpeg|png';
$config['max_size'] = '2048';

$this->load->library('upload', $config);

if(!$this->upload->do_upload()){

    $data['uerrors'] = $this->upload->display_errors();

    if ($data['uerrors']) {
        $this->load->view('partials/header', $data);
        $this->load->view('dashboard/create-post');
        $this->load->view('partials/footer');
    } else {
        $post_image = 'default.jpg';
    }

} else {
    $data = array('upload_data' => $this->upload->data());
    $post_image = $_FILES['userfile']['name'];
}

In the view I have:

<?php foreach ($uerrors as $uerror): ?>
  <span><?php echo $uerror; ?></span>
<?php endforeach; ?>

Yet, I get a Undefined variable: uerrors error.

Here is the entire create() method:

public function create() {

    // Only logged in users can create posts
    if (!$this->session->userdata('is_logged_in')) {
        redirect('login');
    }

    $data = $this->get_data();
    $data['tagline'] = "Add New Post";

    if ($data['categories']) {
        foreach ($data['categories'] as &$category) {
            $category->posts_count = $this->Posts_model->count_posts_in_category($category->id);
        }
    }

    $this->form_validation->set_rules('title', 'Title', 'required');
    $this->form_validation->set_rules('desc', 'Short description', 'required');
    $this->form_validation->set_rules('body', 'Body', 'required');
    $this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');

    if($this->form_validation->run() === FALSE){
        $this->load->view('partials/header', $data);
        $this->load->view('dashboard/create-post');
        $this->load->view('partials/footer');
    } else {
        // Create slug (from title)
        $slug = url_title(convert_accented_characters($this->input->post('title')), 'dash', TRUE);
        $slugcount = $this->Posts_model->slug_count($slug, null);
        if ($slugcount > 0) {
            $slug = $slug."-".$slugcount;
        }

        // Upload image
        $config['upload_path'] = './assets/img/posts';
        $config['allowed_types'] = 'jpg|jpeg|png';
        $config['max_size'] = '2048';

        $this->load->library('upload', $config);

        if(!$this->upload->do_upload()){

            $data['uerrors'] = $this->upload->display_errors();

            if ($data['uerrors']) {
                $this->load->view('partials/header', $data);
                $this->load->view('dashboard/create-post');
                $this->load->view('partials/footer');
            } else {
                $post_image = 'default.jpg';
            }

        } else {
            $data = array('upload_data' => $this->upload->data());
            $post_image = $_FILES['userfile']['name'];
        }

        $this->Posts_model->create_post($post_image, $slug);
        $this->session->set_flashdata('post_created', 'Your post has been created');
        redirect('/');
    }
} 

Where is my mistake?


回答1:


Your upload code looks okay, but you need to update these following changes.

  1. Pass data to your 'dashboard/create-post' view as you have passed to your 'partials/header' view. Your 'dashboard/create-post' view is not getting any upload error messages, so it is saying 'Undefined variable: uerrors'. So, your upload code should be like this -
if(!$this->upload->do_upload()){
    $data['uerrors'] = $this->upload->display_errors();
    if ($data['uerrors']) {
        $this->load->view('partials/header', $data);
        $this->load->view('dashboard/create-post', $data);
        $this->load->view('partials/footer');
    } else {
        $post_image = 'default.jpg';
    }
} else {
    $post_image = $this->upload->data('file_name');
}
  1. As CodeIgniter Documentation says, 'display_errors()' returns string, not array, you don't have to loop through the error. Just echo it on your 'dashboard/create-post' view.

For your convenience, make your upload task in different method so that you can re-use this in update method also. As example -

private function uploadFile(){
    if ($_FILES['userfile']['name'] === '') {
        return array(
            'status' => TRUE,
            'message' => 'No file selected.',
            'file_name' => 'default.jpg'
        );
    }

    // Upload image
    $config['upload_path'] = './assets/img/posts';
    $config['allowed_types'] = 'jpg|jpeg|png';
    $config['max_size'] = '2048';

    $this->load->library('upload', $config);

    if(!$this->upload->do_upload('userfile')){
        return array(
            'status' => FALSE,
            'message' => $this->upload->display_errors('<p class="text-danger ">', '</p>'),
            'file_name' => ''
        );
    }else{
        return array(
            'status' => TRUE,
            'message' => 'File uploaded successfully',
            'file_name' => $this->upload->data('file_name')
        );
    }
}

Then your entire create method should look like this -

public function create() {
    // Only logged in users can create posts
    if (!$this->session->userdata('is_logged_in')) {
        redirect('login');
    }

    $data = $this->get_data();
    $data['tagline'] = "Add New Post";

    if ($data['categories']) {
        foreach ($data['categories'] as &$category) {
            $category->posts_count = $this->Posts_model->count_posts_in_category($category->id);
        }
    }

    $this->form_validation->set_rules('title', 'Title', 'required');
    $this->form_validation->set_rules('desc', 'Short description', 'required');
    $this->form_validation->set_rules('body', 'Body', 'required');
    $this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');

    if($this->form_validation->run() === FALSE){
        $this->load->view('partials/header', $data);
        $this->load->view('dashboard/create-post');
        $this->load->view('partials/footer');
    } else {
        $upload = $this->uploadFile();

        if($upload['status'] === FALSE){
            $data['upload_error'] = $upload['message'];

            $this->load->view('partials/header', $data);
            $this->load->view('dashboard/create-post', $data);
            $this->load->view('partials/footer');
        }else{
            // Create slug (from title)
            $slug = url_title(convert_accented_characters($this->input->post('title')), 'dash', TRUE);
            $slugcount = $this->Posts_model->slug_count($slug, null);
            if ($slugcount > 0) {
                $slug = $slug."-".$slugcount;
            }

            $this->Posts_model->create_post($upload['file_name'], $slug);
            $this->session->set_flashdata('post_created', 'Your post has been created');
            redirect('/');
        }
    }
}

And finally add this line of code on your 'dashboard/create-post' view file, right after file input button.

<?php if(isset($upload_error)) echo $upload_error; ?>

I think all should work.




回答2:


There are three things I picked up here

1) not passing $data to the correct view as mentioned before

2) expecting array instead of string on the view ie wrong data type

3) lastly function do_upload() expects parameter string $field. This is missing that's why you are having only the no upload selected error. If this parametre is set codeigniter really throws wrong filetype error. I did this to test

on my view

<form action="http://localhost:8000/welcome/create" method="post" enctype="multipart/form-data">
          <input type="file" name="lname" ><br>
          <input type="submit" value="Submit">
        </form>

then in my controller

if(!$this->upload->do_upload("lname")){

Upload a wrong file type to test this error. You may need to go an extra length to detect the filetype for the actual upload file.




回答3:


This error tells you that a variable doesn't exist or was not initialized. Looking at this code

$data['uerrors'] = $this->upload->display_errors();

if ($data['uerrors']) {

I think that you probably have a $uerrors variable somewhere (not shown in this code) which was not initialized. Note that I do not believe that the array index 'uerrors' would cause you trouble in the chunk above, because, first of all you define it and second, if you reference an array item which does not exist, then you will get a different error message from the one quoted in the question.




回答4:


Your question is a bit vague. Whatever, the only condition in which the variable $uerrors will set is when create() method will execute which I believe would get executed on POST request. Besides, you didn't mention which part of view is this:

<?php foreach ($uerrors as $uerror): ?>
  <span><?php echo $uerror; ?> </span>
<?php endforeach; ?>

If it's dashboard/create-post view then try passing $data directly to this view instead of passing it to partials/header

Note: I just checked the codeigniter View/Controller samples and I found it to be a good practice to check variable using isset() function call, so instead of executing foreach loop directly, do this:

<? if (isset($uerrors)): ?>
    <? foreach ($uerrors as $uerror): ?>
      <span><?= $uerror; ?></span>
    <? endforeach; ?> 
<? endif; ?> 



回答5:


You need to initialize $data['uerrors'] as null because you are using it on the front end

$data['uerrors'] = '';

or check the value is not empty on the frontend.

Frontend, you can do this as:

<?php  if (isset($uerrors) && $uerrors != '') {
            foreach ($uerrors as $uerror) {
                echo '<span>' . $uerror . '</span>';
            }
        } ?>

Your controller will be:

 $data = array();
        // Upload image
        $config['upload_path'] = './assets/img/posts';
        $config['allowed_types'] = 'jpg|jpeg|png';
        $config['max_size'] = '2048';

        $this->load->library('upload', $config);

        /*You need to initialize  $data['uerrors'] as null because you are using it on front end*/
        $data['uerrors'] = '';
        if (!$this->upload->do_upload('FilePath')) {
            $data['uerrors'] = $this->upload->display_errors();
            $this->load->view('partials/header', $data);
            $this->load->view('dashboard/create-post');
            $this->load->view('partials/footer');
        } else {
            if (isset($_POST{'your_file'})) {
                /*'check your images here that you are receiving from front end'*/
            } else {
                /*If there is no image, then default image is*/
                $post_image = 'default.jpg';
            }
            $data = array('upload_data' => $this->upload->data());
            $post_image = $_FILES['userfile']['name'];
        }

You can further find useful posts on How to upload image in CodeIgniter?




回答6:


I have succeeded to display the upload errors (if upload is attempted, otherwise a default image is used) by modifying create() this way:

public function create() {

    // Only logged in users can create posts
    if (!$this->session->userdata('is_logged_in')) {
        redirect('login');
    }

    $data = $this->get_data();
    $data['tagline'] = "Add New Post";

    if ($data['categories']) {
        foreach ($data['categories'] as &$category) {
            $category->posts_count = $this->Posts_model->count_posts_in_category($category->id);
        }
    }

    $this->form_validation->set_rules('title', 'Title', 'required');
    $this->form_validation->set_rules('desc', 'Short description', 'required');
    $this->form_validation->set_rules('body', 'Body', 'required');
    $this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');

    if($this->form_validation->run() === FALSE){
        $this->load->view('partials/header', $data);
        $this->load->view('dashboard/create-post');
        $this->load->view('partials/footer');
    } else {
        // Create slug (from title)
        $slug = url_title(convert_accented_characters($this->input->post('title')), 'dash', TRUE);
        $slugcount = $this->Posts_model->slug_count($slug, null);
        if ($slugcount > 0) {
            $slug = $slug."-".$slugcount;
        }

        // Upload image
        $config['upload_path'] = './assets/img/posts';
        $config['allowed_types'] = 'jpg|jpeg|png';
        $config['max_size'] = '2048';

        $this->load->library('upload', $config);

        if(!$this->upload->do_upload()){

            $errors = array('error' => $this->upload->display_errors());

            // Display upload validation errors 
            // only if a file is uploaded and there are errors
            if (empty($_FILES['userfile']['name'])) {
                $errors = [];
            }

            if (empty($errors)) {
                $post_image = 'default.jpg';
            } else {
                $data['upload_errors'] = $errors;
            }

        } else {
            $data = array('upload_data' => $this->upload->data());
            $post_image = $_FILES['userfile']['name'];
        }

        if (empty($errors)) {
            $this->Posts_model->create_post($post_image, $slug);
            $this->session->set_flashdata('post_created', 'Your post has been created');
            redirect('/');
        } else {
            $this->load->view('partials/header', $data);
            $this->load->view('dashboard/create-post');
            $this->load->view('partials/footer');
        }
    }
}

In the create-post.php view I have:

<?php if(isset($upload_errors)){
   foreach ($upload_errors as $upload_error) {
    echo $upload_error;
   }
 }?>


来源:https://stackoverflow.com/questions/59584924/how-to-display-disallowed-file-type-error-message-in-case-of-upload-in-codeignit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!