Вопрос

Нам нужно создать интерфейс управления файлами, который интегрируется с текущим веб-сайтом клиента, построенным на Cakephp.

Файловый менеджер должен позволять пользователям видеть только те файлы, к которым у них есть разрешения.

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

Это не проблема для многих систем управления файлами, которые мы можем приобрести, но ни одна из тех, что я могу найти, не интегрируется с их текущей системой входа в систему.Клиент хочет, чтобы пользователи входили в систему только один раз, чтобы получить доступ к своему пользовательскому CP и своим файлам.Итак, насколько я понимаю, наш единственный вариант — это создать интерфейс управления файлами самостоятельно.

Какие параметры мы можем разрешить загрузку с помощью PHP?Я понимаю, что нам нужно увеличить лимит загрузки php, но есть ли потолок, который позволяет php/apache?

Размер файлов, скорее всего, будет ограничен примерно 150 МБ, если это актуально, однако могут быть ситуации, когда размеры файлов будут больше.

Также, что можно и чего нельзя делать при загрузке/управлении файлами на сервере Linux?

Полагаю, у меня нет настоящих «конкретных» вопросов, но хотелось бы получить совет о том, с чего начать и о некоторых типичных ловушках, с которыми мы столкнемся.

Это было полезно?

Решение

На самом деле управление файлами довольно простое.Вот несколько советов, которые могут указать вам правильное направление.

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

Есть несколько переменных, на которые вы захотите повлиять, чтобы разрешить загрузку большего размера.Я рекомендую использовать директивы Apache, чтобы ограничить эти изменения конкретным файлом:

<Directory /home/deploy/project/uploader>
    php_value max_upload_size "200M"
    php_value post_max_size "200M"
    php_value max_input_time "1800"

    # this one depends on how much processing you are doing to the file
    php_value memory_limit "32M" 
</Directory>

Архитектура:

Создайте таблицу базы данных, в которой будет храниться информация о каждом файле.

CREATE TABLE `File` (
  `File_MNID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Owner_Field` enum('User.User_ID', 'Resource.Resource_ID') NOT NULL,
  `Owner_Key` int(10) unsigned NOT NULL,
  `ContentType` varchar(64) NOT NULL,
  `Size` int(10) NOT NULL,
  `Hash` varchar(40) NOT NULL,
  `Name` varchar(128) NOT NULL,
  PRIMARY KEY (`File_MNID`),
  KEY `Owner` (`Owner_Field`,`Owner_Key`)
) ENGINE=InnoDB 

Что Owner_Field и Owner_Key?Простой способ сказать, какой «объект» владеет файлом.В данном конкретном случае загружалось несколько типов файлов.В вашем случае простой User_ID поле может быть достаточным.

Цель сохранения владельца состоит в том, чтобы вы могли ограничить круг лиц, которые могут загружать и удалять файл.Это будет иметь решающее значение для защиты загрузок.

Вот пример класса который можно использовать для принятия загрузок файлов из браузера.Конечно, вам придется изменить его под свои нужды.

В следующем коде следует отметить несколько моментов.Поскольку он используется с сервером приложений и файловым сервером, есть несколько вещей, которые нужно «заменить».

  1. Любые случаи App::CallAPI(...) необходимо будет заменить запросом или набором запросов, которые делают «то же самое».
  2. Любые случаи App::$FS->... необходимо будет заменить правильными функциями обработки файлов в PHP, такими как move_uploaded_file, readfile, и т. д...

Вот.Имейте в виду, что здесь есть функции, которые позволяют вам видеть файлы, принадлежащие данному пользователю, удалять файлы и так далее и тому подобное.Подробное объяснение внизу...

<?php

class FileClient
{
    public static $DENY     = '/\.ade$|\.adp$|\.asp$|\.bas$|\.bat$|\.chm$|\.cmd$|\.com$|\.cpl$|\.crt$|\.exe$|\.hlp$|\.hta$|\.inf$|\.ins$|\.isp$|\.its$| \.js$|\.jse$|\.lnk$|\.mda$|\.mdb$|\.mde$|\.mdt,\. mdw$|\.mdz$|\.msc$|\.msi$|\.msp$|\.mst$|\.pcd$|\.pif$|\.reg$|\.scr$|\.sct$|\.shs$|\.tmp$|\.url$|\.vb$|\.vbe$|\.vbs$|vsmacros$|\.vss$|\.vst$|\.vsw$|\.ws$|\.wsc$|\.wsf$|\.wsh$/i';

    public static $MAX_SIZE = 5000000;

    public static function SelectList($Owner_Field, $Owner_Key)
    {
        $tmp = App::CallAPI
        (
            'File.List',
            array
            (
                'Owner_Field' => $Owner_Field,
                'Owner_Key' => $Owner_Key,
            )
        );

        return $tmp['Result'];
    }

    public static function HandleUpload($Owner_Field, $Owner_Key, $FieldName)
    {
        $aError = array();

        if(! isset($_FILES[$FieldName]))
            return false;
        elseif(! is_array($_FILES[$FieldName]))
            return false;
        elseif(! $_FILES[$FieldName]['tmp_name'])
            return false;
        elseif($_FILES[$FieldName]['error'])
            return array('An unknown upload error has occured.');

        $sPath = $_FILES[$FieldName]['tmp_name'];
        $sHash = sha1_file($sPath);
        $sType = $_FILES[$FieldName]['type'];
        $nSize = (int) $_FILES[$FieldName]['size'];
        $sName = $_FILES[$FieldName]['name'];

        if(preg_match(self::$DENY, $sName))
        {
            $aError[] = "File type not allowed for security reasons.  If this file must be attached, please add it to a .zip file first...";
        }

        if($nSize > self::$MAX_SIZE)
        {
            $aError[] = 'File too large at $nSize bytes.';
        }

        // Any errors? Bail out.
        if($aError)
        {
            return $aError;
        }


        $File = App::CallAPI
        (
            'File.Insert',
            array
            (
                'Owner_Field'        => $Owner_Field,
                'Owner_Key'            => $Owner_Key,
                'ContentType'        => $sType,
                'Size'                => $nSize,
                'Hash'                => $sHash,
                'Name'                => $sName,
            )
        );

        App::InitFS();
        App::$FS->PutFile("File_" . $File['File_MNID'], $sPath);

        return $File['File_MNID'];

    }

    public static function Serve($Owner_Field, $Owner_Key, $File_MNID)
    {
        //Also returns the name, content-type, and ledger_MNID
        $File    = App::CallAPI
        (
            'File.Select',
            array
            (
                'Owner_Field'     => $Owner_Field,
                'Owner_Key'     => $Owner_Key,
                'File_MNID'     => $File_MNID
            )
        );

        $Name     = 'File_' . $File['File_MNID'] ;

        //Content Header for that given file
        header('Content-disposition: attachment; filename="' . $File['Name'] . '"');
        header("Content-type:'" . $File['ContentType'] . "'");

        App::InitFS();
        #TODO
        echo App::$FS->GetString($Name);

    }

    public static function Delete($Owner_Field, $Owner_Key, $File_MNID)
    {

        $tmp = App::CallAPI
        (
            'File.Delete',
            array
            (
                'Owner_Field' => $Owner_Field,
                'Owner_Key' => $Owner_Key,
                'File_MNID' => $File_MNID,
            )
        );

        App::InitFS();
        App::$FS->DelFile("File_" . $File_MNID);
    }

    public static function DeleteAll($Owner_Field, $Owner_Key)
    {
        foreach(self::SelectList($Owner_Field, $Owner_Key) as $aRow)
        {
            self::Delete($Owner_Field, $Owner_Key, $aRow['File_MNID']);
        }
    }

}

Примечания:

Имейте в виду, что этот класс НЕ реализует безопасность.Предполагается, что перед вызовом у вызывающего абонента есть аутентифицированные Owner_Field и Owner_Key. FileClient::Serve(...) и т. д...

Уже немного поздно, поэтому, если что-то из этого не имеет смысла, просто оставьте комментарий.Хорошего вечера, и я надеюсь, что это кому-то поможет.

ПС.Пользовательский интерфейс может представлять собой простые таблицы, поля для загрузки файлов и т. д.Или вы можете проявить фантазию и использовать флеш-загрузчик...

Другие советы

Я рекомендую взглянуть на следующие примеры кода CakePHP, предоставленные сообществом:

вот хороший выбор.Для этого требуется установить клиент ПК и однофайловый php-сервер.Но он работает быстро!

http://the-sync-star.com/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top