将CodeIgniter多文件DropZone上传器代码划分为MVC?

时间:2017-12-11 18:43:04

标签: codeigniter codeigniter-3 dropzone

我是CodeIgniter的新手,我正在尝试将工作DropZone多文件上传器转换为MVC CodeIgniter格式。我在这里看到了一些其他示例,但需要获取我的特定代码的建议。

我知道如何将上传/表单页面放在视图中并通过控制器加载。但是,表单处理程序代码是我需要帮助的地方。

上传/表单页面:

<head>
<script type="text/javascript" src="js/jquery-2.1.1.js"></script>
<!-- Add Dropzone -->
<link rel="stylesheet" type="text/css" href="css/dropzone.css" />
<script type="text/javascript" src="js/dropzone.js"></script>
</head>
<body>
<div class="image_upload_div">
<form action="upload_thumbnails.php" class="dropzone">
</form>
</div>  

<script type="text/javascript">
//Disabling autoDiscover
Dropzone.autoDiscover = false;
$(function() {
    //Dropzone class
    var myDropzone = new Dropzone(".dropzone");
    myDropzone.on("queuecomplete", function() {
        //Redirect URL
        //window.location.href = 'http://php.net';
    });
});
</script>
</body>

表单处理程序代码的哪些部分应该放在模型与控制器中?这是我正在努力的部分。

表单处理程序代码:

if(!empty($_FILES)){    

  function createThumbnail($filename) {
    $final_width_of_image = 200;
    $path_to_image_directory = 'uploads/';
    $path_to_thumbs_directory = 'uploads/thumbs/';

    if(preg_match('/[.](jpg)$/', $filename)) {
        $im = imagecreatefromjpeg($path_to_image_directory . $filename);
    } else if (preg_match('/[.](gif)$/', $filename)) {
        $im = imagecreatefromgif($path_to_image_directory . $filename);
    } else if (preg_match('/[.](png)$/', $filename)) {
        $im = imagecreatefrompng($path_to_image_directory . $filename);
    }

    $ox = imagesx($im);
    $oy = imagesy($im);
    $nx = $final_width_of_image;
    $ny = floor($oy * ($final_width_of_image / $ox));
    $nm = imagecreatetruecolor($nx, $ny);
    if(!imagecopyresized($nm, $im, 0,0,0,0,$nx,$ny,$ox,$oy)){
        header("HTTP/1.0 500 Internal Server Error");
        echo 'Thumbnail Not created';
        exit(); 
    }
    if(!file_exists($path_to_thumbs_directory)) {
        if(!mkdir($path_to_thumbs_directory)) {
            header("HTTP/1.0 500 Internal Server Error");
            echo 'Thumbnail Not Created';
            exit();
        } 
    }
    // Save new thumbnail image
    imagejpeg($nm, $path_to_thumbs_directory . $filename);

  }

//database configuration
$dbHost = 'localhost';
$dbUsername = 'insertnamehere';
$dbPassword = 'insertpwhere';
$dbName = 'ci_local';
//connect with the database
$conn = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);
if($mysqli->connect_errno){
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

$targetDir = "uploads/";
$fileName = $_FILES['file']['name'];
$targetFile = $targetDir.$fileName;

if(move_uploaded_file($_FILES['file']['tmp_name'],$targetFile)){
    // NEW
    //createThumbnail($file['file']['name']);
    createThumbnail($fileName);
    // NEW

    //insert file information into db table
    $conn->query("INSERT INTO files (file_name, uploaded) VALUES('".$fileName."','".date("Y-m-d H:i:s")."')");
} else {
    echo "Ooops";
}

}

非常感谢任何建议。

1 个答案:

答案 0 :(得分:1)

你的createThumbnail函数是一个很好的例子,应该放在模型或库或帮助器中。帮助器只包含函数,而库或模型是基于类的,因此可以访问类属性并具有构造函数。我倾向于使它成为一个库或一个帮助器,因为它没有耦合(因此可重复使用)任何特定或其他功能。

通常,您只想在任何不在控制器中的函数中返回或抛出异常。

  1. 这允许您将输出设置在一个文件中而不是必须 搜索您的模型,库,.etc。如果你想改变 您的输出(例如,如果您计划使用AJAX)。
  2. 还允许没有紧密耦合的代码库 很容易移植到其他可能不同的安装。
  3. 善于阅读。
  4. 模型

    任何与数据库相关的内容都应该放在模型中,因为模型代表了应用程序使用的数据逻辑或实际数据。您应该使用Codeigniter的内置数据库函数,而不是初始化数据库并自己运行查询。您的插入或更新语句应移动到与控制器相关的模型中。

    控制器

    您的控制器仅用于加载模型以及视图可能需要的任何变量。它也应该用于设置响应,无论是flash消息还是json编码。在许多示例中,在执行相关模型中存在的CRUD操作之前,它还用于form_validation或数据检查。

    tl; dr任何与数据库相关的内容都在模型中,任何可重用且没有紧密耦合的内容都会进入库中,或者如果它与oop没有特定的关系就会进入帮助器(如数组排序算法),任何东西表格/输入/查看/响应相关的内容在控制器中。

    大概你可以做这样的事情(代码可能无法开箱即用;我使用自己的实现,与默认的dz行为不同,因为我使用jquerys也可以排序...我也不确定错误处理正如我那样使用另一种技术):

    // byte_helper.php
    
    /**
     * Gets max upload size from post_max_size and upload_max_filesize
     * Returns whichever is smaller
     *
     * @return int
     */
    function file_upload_max_size() {
        $max_size = convert_to_bytes(ini_get('post_max_size'));
        $upload_max = convert_to_bytes(ini_get('upload_max_filesize'));
        if ($upload_max > 0 && $upload_max < $max_size) {
            $max_size = $upload_max;
        }
        return $max_size;
    }
    
    /**
     * Converts KB (K) through GB (G) to bytes
     * 
     * @param string $from
     * @return int bytes
     */
    function convert_to_bytes($from) {
        $number = filter_var($from, FILTER_SANITIZE_NUMBER_INT);
        $type = strtoupper(str_replace($number, '', $from));
        switch ($type) {
            case "KB":
            case "K":
                $number = $number * 1024;
                break;
            case "MB":
            case "M":
                $number = $number * pow(1024, 2);
                break;
            case "GB":
            case "G":
                $number = $number * pow(1024, 3);
                break;
        }
        return fix_integer_overflow($number);
    }
    
    /**
     * Fixes integer overflow
     * 
     * @param int $size
     * @return int
     */
    function fix_integer_overflow($size) {
        if ($size < 0) {
            $size += 2.0 * (PHP_INT_MAX + 1);
        }
        return $size;
    }
    
    class Dropzone_controller extends CI_Controller {
    
        public function upload() {
            if (!$this->input->is_ajax_request()) {
                exit('No direct script access allowed');
            }
            $this->load->helper('byte');
            $config['upload_path'] = ''; // upload directory realpath
            $config['file_name'] = md5(time()); // I like to set my own filename
            $config['overwrite'] = true;
            $config['allowed_types'] = 'jpg|jpeg|png|gif';
            $config['max_size'] = file_upload_max_size();
            $config['file_ext_tolower'] = true;
            $this->load->library('upload', $config);
            if (!$this->upload->do_upload('file')) {
                $this->dz_error($this->upload->display_errors('', '<br>'));
            }
            $data = $this->upload->data();
            $full_path = realpath($data['full_path']); // CI uses weird slashes
            // here you can use imagelib to resize if you want, I personally
            // like to use verot's class upload for that
            $this->load->model('dropzone_model');
            if (!$this->dropzone_model->add_image($full_path)) {
                @unlink($full_path); // remove orphaned image
                $this->dz_error('Failed to add image to the database!');
            }
            $this->dz_success();
        }
    
        // https://stackoverflow.com/questions/27030652/how-to-display-error-message-of-jquery-dropzone
        private function dz_error($error) {
            $this->output
                    ->set_header("HTTP/1.0 400 Bad Request")
                    ->set_output($error)
                    ->_display();
            exit;
        }
    
        private function dz_success() {
            // don't really need to do anything here?
        }
    
    }
    
    class Dropzone_model extends CI_Model {
    
        public function add_image($full_path) {
            return $this->db->insert('sometable', array('image' => $full_path));
        }
    
    }