Проблемы с CodeIgniter (и allow_types) - PullRequest
       3

Проблемы с CodeIgniter (и allow_types)

0 голосов
/ 01 сентября 2011

Утро, ребята.

Я пытаюсь использовать Plupload вместе с CodeIgniter. Я пробовал загружать до Plupload, и он работал потрясающе, основная проблема с uploadify заключается в том, что он никогда не отправлял код CSRF, независимо от того, что я использовал, это было действительно странно, поэтому я просмотрел Plupload и заставил его работать как положено за считанные минуты. Однако он ТОЛЬКО хорошо работает с загрузчиком HTML5, а не с загрузчиком Flash.

Просмотр журналов Я нашел причину, по которой он не работал: при использовании класса загрузки файлов CodeIgniter.

Так как я делаю загрузчик объемных изображений, я настроил его для разрешения «jpg, gif, png, jpeg», но обнаружил, что загрузчик отклоняет петицию загрузки, так как я загружаю неправильный файл type_file (который я нашел как octet / stream - wtf?).

После процесса загрузки я обрабатывал изображение (создавал большие пальцы, водяные знаки, обрезал и т. Д.), Поэтому, если я настроил разрешение для всех типов файлов, обработка изображений не будет работать вообще.

Я думал о том, чтобы сделать что-то вроде загрузки файла (с разрешением MIME TYPE octet / stream), затем преобразовать его в изображение (с помощью функций imagecreatefromstring и file_get_contents) и затем обработать его индивидуально.

Если у вас есть другая идея, дайте мне знать

1 Ответ

4 голосов
/ 02 сентября 2011

Перед тем, как продолжить, я рекомендую вам отказаться от любого флэш-загрузчика и выбрать https://github.com/blueimp/jQuery-File-Upload, который всегда остается HTML5 и обратно совместим. В большинстве случаев вы не увидите бары загрузки, но Flash отсутствует, и вам не нужно вносить никаких изменений в CodeIgniter.

Следующее не очень уточнено. Фактически, я отказываюсь от поддержки загрузки Flash в моем приложении из следующей версии.

Любая загрузка, сделанная через Flash, будет приниматься сервером как application / octet-stream. Это перестает быть проблемой, когда в файле /application/config/mime.php вы добавляете «application / octet-stream» к интересующим вас типам файлов. Вот пример , посмотрите внизу файл.

В настоящее время CSRF представляет собой не столько проблему, сколько то, что у Flash есть свои собственные куки, что означает, что он похож на совершенно отдельный браузер. Прежде чем пытаться отправить CSRF, мы должны вставить во Flash идентификатор сеанса, который CodeIgniter использует для вашей идентификации. Вам также придется изменить в /application/config/config.php

$config['sess_match_useragent'] = FALSE;

Если вы хотите использовать Uploadify3 (это должно работать и для Uploadify 2 и Plupload), сначала нужно добавить /application/libraries/MY_Session.php, чтобы можно было отправлять данные сеанса также через POST.

Просто используйте этот файл: https://github.com/woxxy/FoOlSlide/blob/a7522d747fe406da18ce18ae9763f083b89eb91e/application/libraries/MY_Session.php

Затем в вашем контроллере вы должны сделать возможным получение идентификатора сеанса в любое время.

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

Ваш контроллер загрузки должен быть довольно стандартной функцией загрузки. Убедитесь, что вы используете правильное имя при загрузке ("userfile").

Теперь самое худшее: просмотр файла. Я мог бы удалить некоторые детали, но я думаю, что некоторые дополнительные данные помогут вам их кодировать без необходимости искать слишком много в 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>
...