【问题标题】:Problems with CodeIgniter (and allowed_types)CodeIgniter(和 allowed_types)的问题
【发布时间】:2011-11-08 12:50:16
【问题描述】:

早安。

我正在尝试将 Plupload 与 CodeIgniter 一起使用。我在 Plupload 之前尝试了 uploadify,它的效果很棒,uploadify 的主要问题是它从不发送 CSRF 代码,无论我使用什么,这真的很奇怪,所以我审查了 Plupload,并在几分钟内让它按预期工作。但是,它只适用于 HTML5 上传器,不适用于 Flash 上传器。

查看日志我发现它不起作用的原因:在使用 CodeIgniter 文件上传类时。

由于我正在做一个批量图像上传器,我将其设置为允许“jpg,gif,png,jpeg”,但发现上传器拒绝了上传请求,因为我上传了错误的 type_file(我发现它是八位字节) /stream - wtf?)。

在上传过程之后,我正在处理图像(生成拇指、水印、裁剪等),所以如果我将其设置为允许所有文件类型,图像处理将根本不起作用。

我的想法是上传文件(允许八位字节/流 MIME 类型)然后将其转换为图像(使用 imagecreatefromstring 和 file_get_contents 函数),然后单独处理它。

如果你有任何其他想法,请告诉我

【问题讨论】:

    标签: php jquery codeigniter plupload


    【解决方案1】:

    在继续之前,我建议您放弃任何 Flash 上传程序,并选择始终保持 HTML5 并向后兼容的 https://github.com/blueimp/jQuery-File-Upload。最多你不会看到上传栏,但没有 Flash,你不必对 CodeIgniter 做任何修改。

    以下不是很精炼。事实上,从下一个版本开始,我的应用程序中将不再支持 Flash 上传。

    通过 Flash 上传的任何内容都将作为 application/octet-stream 被服务器接收。 当您在文件 /application/config/mime.php 中将“application/octet-stream”添加到您感兴趣的文件类型中时,这不再是一个问题。这里是an example,请查看文件底部。

    目前,CSRF 问题不大,因为 Flash 有自己的 cookie,这意味着它就像一个完全独立的浏览器。在尝试发送 CSRF 之前,我们必须将 CodeIgniter 用来识别您的 Session ID 放入 Flash。您还必须更改 /application/config/config.php

    $config['sess_match_useragent'] = FALSE;
    

    如果您想使用 Uploadify3(这也适用于 Uploadify 2 和 Plupload),您首先必须添加 /application/libraries/MY_Session.php 才能通过 POST 发送 Session 数据。

    只需使用此文件: https://github.com/woxxy/FoOlSlide/blob/a7522d747fe406da18ce18ae9763f083b89eb91e/application/libraries/MY_Session.php

    然后在你的控制器中,你必须让它可以随时检索会话 ID。

    function get_sess_id()
    {
        $this->output->set_output(json_encode(array('session' => $this->session->get_js_session(), 'csrf' => $this->security->get_csrf_hash())));
    }
    

    您的上传控制器应该是一个非常标准的上传功能。确保在上传时使用正确的名称(“用户文件”)。

    现在,最糟糕的部分是:视图文件。我本可以删除一些细节,但我认为一些额外的数据将帮助您编写代码,而无需在 Uploadify3 中查找太多。

    <script type="text/javascript">
        function updateSession()
        {
            jQuery.post('<?php echo site_url('/admin/series/get_sess_id'); ?>', 
            function(result){
    
                jQuery('#file_upload_flash').uploadifySettings( 'postData', {
                    'ci_sessionz' : result.session, 
                    '<?php echo $this->security->get_csrf_token_name(); ?>' : result.csrf, 
                    'chapter_id' : <?php echo $chapter->id; ?>
                }, false );
                setTimeout('updateSession()', 6000);
            }, 'json');
        }
    
        jQuery(document).ready(function() {
            jQuery('#file_upload_flash').uploadify({
                'swf'  : '<?php echo site_url(); ?>assets/uploadify/uploadify.swf',
                'uploader'    : '<?php echo site_url('/admin/series/upload/compressed_chapter'); ?>',
                'cancelImage' : '<?php echo site_url(); ?>assets/uploadify/uploadify-cancel.png',
                'checkExisting' : false,
                'preventCaching' : false,
                'multi' : true,
                'buttonText' : '<?php echo _('Use flash upload'); ?>',
                'width': 200,
                'auto'      : true,
                'requeueErrors' : true,
                'uploaderType'    : 'flash',
                'postData' : {},
                'onSWFReady'  : function() {
                    updateSession();
                },
                'onUploadSuccess' : function(file, data, response) {
                    var files = jQuery.parseJSON(data);
                    var fu = jQuery('#fileupload').data('fileupload');
                    fu._adjustMaxNumberOfFiles(-files.length);
                    fu._renderDownload(files)
                    .appendTo(jQuery('#fileupload .files'))
                    .fadeIn(function () {
                        jQuery(this).show();
                    });
                }   
            });
        });
    
    </script>
    <div id="file_upload_flash"></div>
    

    现在,如果工作还不够……Uploadify3 中有一个错误,它不会触发一两个回调。

    这里是固定版本的代码:https://github.com/woxxy/FoOlSlide/blob/a7522d747fe406da18ce18ae9763f083b89eb91e/assets/uploadify/jquery.uploadify.js

    你可能想要缩小它。

    但是如果您想使用 jQuery-File-Upload 怎么办?

    那么您所要做的就是稍微调整一下您的控制器。这是一个例子(我也不会清理这段代码,因为它可能只会使上传控制器损坏)

    function upload()
    {
        $info = array();
    
        // compatibility for flash uploader and browser not supporting multiple upload
        if (is_array($_FILES['Filedata']) && !is_array($_FILES['Filedata']['tmp_name']))
        {
            $_FILES['Filedata']['tmp_name'] = array($_FILES['Filedata']['tmp_name']);
            $_FILES['Filedata']['name'] = array($_FILES['Filedata']['name']);
        }
    
        for ($file = 0; $file < count($_FILES['Filedata']['tmp_name']); $file++)
        {
            $valid = explode('|', 'png|zip|rar|gif|jpg|jpeg');
            if (!in_array(strtolower(substr($_FILES['Filedata']['name'][$file], -3)), $valid))
                continue;
    
            if (!in_array(strtolower(substr($_FILES['Filedata']['name'][$file], -3)), array('zip', 'rar')))
                $pages = $this->files_model->page($_FILES['Filedata']['tmp_name'][$file], $_FILES['Filedata']['name'][$file], $this->input->post('chapter_id'));
            else
                $pages = $this->files_model->compressed_chapter($_FILES['Filedata']['tmp_name'][$file], $_FILES['Filedata']['name'][$file], $this->input->post('chapter_id'));
    
            foreach ($pages as $page)
            {
                $info[] = array(
                    'name' => $page->filename,
                    'size' => $page->size,
                    'url' => $page->page_url(),
                    'thumbnail_url' => $page->page_url(TRUE),
                    'delete_url' => site_url("admin/series/delete/page"),
                    'delete_data' => $page->id,
                    'delete_type' => 'POST'
                );
            }
        }
    
        // return a json array
        echo json_encode($info);
        return true;
    }
    
    
    function get_file_objects()
    {
        // Generate JSON File Output (Required by jQuery File Upload)
        header('Content-type: application/json');
        header('Pragma: no-cache');
        header('Cache-Control: private, no-cache');
        header('Content-Disposition: inline; filename="files.json"');
    
        $id = $this->input->post('id');
        $chapter = new Chapter($id);
        $pages = $chapter->get_pages();
        $info = array();
        foreach ($pages as $page)
        {
            $info[] = array(
                'name' => $page['filename'],
                'size' => intval($page['size']),
                'url' => $page['url'],
                'thumbnail_url' => $page['thumb_url'],
                'delete_url' => site_url("admin/series/delete/page"),
                'delete_data' => $page['id'],
                'delete_type' => 'POST'
            );
        }
    
        echo json_encode($info);
        return true;
    }
    

    并添加更多精彩的视图代码(这次几乎是来自 jQuery 上传的库存)

    <div id="fileupload">
        <link href="<?php echo site_url(); ?>assets/jquery-file-upload/jquery-ui.css" rel="stylesheet" id="theme" />
        <link href="<?php echo site_url(); ?>assets/jquery-file-upload/jquery.fileupload-ui.css" rel="stylesheet" />
        <?php echo form_open_multipart(""); ?>
        <div class="fileupload-buttonbar">
            <label class="fileinput-button">
                <span>Add files...</span>
                <input type="file" name="Filedata[]" multiple>
            </label>
            <button type="submit" class="start">Start upload</button>
            <button type="reset" class="cancel">Cancel upload</button>
            <button type="button" class="delete">Delete files</button>
        </div>
        <?php echo form_close(); ?>
        <div class="fileupload-content">
            <table class="files"></table>
            <div class="fileupload-progressbar"></div>
        </div>
    </div>
    <script id="template-upload" type="text/x-jquery-tmpl">
        <tr class="template-upload{{if error}} ui-state-error{{/if}}">
            <td class="preview"></td>
            <td class="name">${name}</td>
            <td class="size">${sizef}</td>
            {{if error}}
            <td class="error" colspan="2">Error:
                {{if error === 'maxFileSize'}}File is too big
                {{else error === 'minFileSize'}}File is too small
                {{else error === 'acceptFileTypes'}}Filetype not allowed
                {{else error === 'maxNumberOfFiles'}}Max number of files exceeded
                {{else}}${error}
                {{/if}}
            </td>
            {{else}}
            <td class="progress"><div></div></td>
            <td class="start"><button>Start</button></td>
            {{/if}}
            <td class="cancel"><button>Cancel</button></td>
        </tr>
    </script>
    <script id="template-download" type="text/x-jquery-tmpl">
        <tr class="template-download{{if error}} ui-state-error{{/if}}">
            {{if error}}
            <td></td>
            <td class="name">${name}</td>
            <td class="size">${sizef}</td>
            <td class="error" colspan="2">Error:
                {{if error === 1}}File exceeds upload_max_filesize (php.ini directive)
                {{else error === 2}}File exceeds MAX_FILE_SIZE (HTML form directive)
                {{else error === 3}}File was only partially uploaded
                {{else error === 4}}No File was uploaded
                {{else error === 5}}Missing a temporary folder
                {{else error === 6}}Failed to write file to disk
                {{else error === 7}}File upload stopped by extension
                {{else error === 'maxFileSize'}}File is too big
                {{else error === 'minFileSize'}}File is too small
                {{else error === 'acceptFileTypes'}}Filetype not allowed
                {{else error === 'maxNumberOfFiles'}}Max number of files exceeded
                {{else error === 'uploadedBytes'}}Uploaded bytes exceed file size
                {{else error === 'emptyResult'}}Empty file upload result
                {{else}}${error}
                {{/if}}
            </td>
            {{else}}
            <td class="preview">
                {{if thumbnail_url}}
                <a href="${url}" target="_blank"><img src="${thumbnail_url}"></a>
                {{/if}}
            </td>
            <td class="name">
                <a href="${url}"{{if thumbnail_url}} target="_blank"{{/if}}>${name}</a>
            </td>
            <td class="size">${sizef}</td>
            <td colspan="2"></td>
            {{/if}}
            <td class="delete">
                <button data-type="${delete_type}" data-url="${delete_url}" data-id="${delete_data}">Delete</button>
            </td>
        </tr>
    </script>
    <script src="<?php echo site_url(); ?>assets/js/jquery-ui.js"></script>
    <script src="<?php echo site_url(); ?>assets/js/jquery.tmpl.js"></script>
    <script src="<?php echo site_url(); ?>assets/jquery-file-upload/jquery.fileupload.js"></script>
    <script src="<?php echo site_url(); ?>assets/jquery-file-upload/jquery.fileupload-ui.js"></script>
    <script src="<?php echo site_url(); ?>assets/jquery-file-upload/jquery.iframe-transport.js"></script>
    
    <script type="text/javascript">
    
        jQuery(function () {
            jQuery('#fileupload').fileupload({
                url: '<?php echo site_url('/admin/series/upload/compressed_chapter'); ?>',
                sequentialUploads: true,
                formData: [
                    {
                        name: 'chapter_id',
                        value: <?php echo $chapter->id; ?>
                    }
                ]
            });
    
            jQuery.post('<?php echo site_url('/admin/series/get_file_objects'); ?>', { id : <?php echo $chapter->id; ?> }, function (files) {
                var fu = jQuery('#fileupload').data('fileupload');
                fu._adjustMaxNumberOfFiles(-files.length);
                fu._renderDownload(files)
                .appendTo(jQuery('#fileupload .files'))
                .fadeIn(function () {
                    jQuery(this).show();
                });
    
            });
    
            jQuery('#fileupload .files a:not([target^=_blank])').live('click', function (e) {
                e.preventDefault();
                jQuery('<iframe style="display:none;"></iframe>')
                .prop('src', this.href)
                .appendTo('body');
            });
    
        });
    
    </script>
    

    【讨论】:

    • 优秀的答案,非常详细,现在我更清楚地了解了这一切背后的所有问题。我显然更喜欢 HTML5 上传器,但在某些情况下(旧浏览器)我需要 Flash 支持。尝试使用 Uploadify 3,但它甚至没有启动上传程序。我会再试一次并告诉你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 2014-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    相关资源
    最近更新 更多