Pergunta

Precisamos criar uma interface de gerenciamento de arquivos que integra com clientes sítio web actual construída sobre CakePHP.

O gerenciador de arquivos só devem deixar os usuários ver os arquivos que tem permissões também.

O usuário será capaz de fazer upload de arquivos (de qualquer tamanho) e têm outros usuários baixar os arquivos (se as permissões permitem).

Este não é um problema para muitos sistemas de gerenciamento de arquivos que pode comprar, mas nenhum que eu possa encontrar irá integrar com o seu log atual no sistema. O cliente só quer que os usuários façam login uma vez para acessar o seu CP usuário e seus arquivos. Assim, tanto quanto eu posso ver a nossa única opção é construir uma gestão de arquivo de interface de nós mesmos.

O que são algumas das opções que temos para permitir uploads usando PHP? Eu entendo que é preciso aumentar o limite de upload php, mas existe um teto que php / apache irá permitir?

Os arquivos provavelmente vai coroar para fora em cerca de 150MB se isso é relevante, no entanto, pode haver situações em que o tamanho do arquivo será maior.

Também o que é o fazer e não fazer de arquivo de upload / controle em um servidor Linux?

Suponho que não têm verdadeiras questões 'específicos', mas gostaria de alguns conselhos sobre onde começar e algumas das armadilhas típicas que vai correr em.

Foi útil?

Solução

Gerenciamento de arquivos é bastante fácil, na verdade. Aqui estão algumas sugestões que podem apontar na direção certa.

Em primeiro lugar, se esta é uma situação servidor web com balanceamento de carga, você vai precisar de intensificar a complexidade um pouco a fim de colocar os arquivos em um lugar comum. Se for esse o caso, pingue-me e eu vou ser feliz para enviar-lhe o nosso servidor de arquivos super-luz / cliente que usamos para essa mesma situação.

Existem algumas variáveis ??que você vai querer afetar de forma a permitir envios maiores. Eu recomendo usando Apache directivas para limitar essas alterações em um arquivo em particular:

<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>

Arquitetura:

Criar uma tabela de banco de dados que armazena algumas informações sobre cada arquivo.

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 

O que é Owner_Field e Owner_Key? Uma maneira simples de dizer o que "entidade" é dono do arquivo. Neste caso específico, havia vários tipos de arquivos que estão sendo carregados. No seu caso, um campo User_ID simples pode ser adequada.

A finalidade de armazenar o proprietário é para que você pode restringir quem pode baixar e excluir o arquivo. Isso será crucial para proteger os downloads.

Aqui está uma classe de exemplo que pode ser usado para aceitar os uploads de arquivos a partir do browser. Você precisará modificá-lo para atender, é claro.

Há algumas coisas a notar sobre o seguinte código. Uma vez que este é usado com um servidor de aplicativos e um servidor de arquivos, há algumas coisas para "substituir".

  1. Qualquer ocorrências de App::CallAPI(...) terá de ser substituída por uma consulta ou conjunto de consultas que fazem a "mesma coisa".
  2. Qualquer ocorrências de App::$FS->... terá de ser substituído com a manipulação do arquivo correto funções em PHP como move_uploaded_file, readfile, etc ...

Aqui está. Tenha em mente que existem funções aqui que lhe permitem ver os arquivos de propriedade de um determinado usuário, apagar arquivos, e assim por diante e assim por diante. Mais explicação na parte inferior ...

<?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']);
        }
    }

}

Notas:

Por favor, tenha em mente que esta classe não implementar a segurança. Assume-se que o chamador tem um Owner_Field e Owner_Key autenticado antes de chamar FileClient::Serve(...) etc ...

É um pouco tarde, por isso, se alguns dos isso não faz sentido, basta deixar um comentário. Tenha uma ótima noite, e eu espero que isso ajude alguns.

PS. A interface de usuário pode ser tabelas simples e campos de upload de arquivos, etc .. Ou você poderia ser fantasia e usar um flash uploader de ...

Outras dicas

Eu recomendo ter um olhar para os seguintes exemplos de código CakePHP contribuídos pela comunidade:

aqui é uma boa escolha. Ela exige que você instalar um cliente PC e um único servidor de arquivos php. Mas corre rápido!

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top