Pregunta

Necesitamos crear una interfaz de administración de archivos que se integre con el sitio web actual del cliente creado en cakephp.

El administrador de archivos solo debe permitir que los usuarios vean los archivos para los que también tienen permisos.

El usuario podrá cargar archivos (de cualquier tamaño) y hacer que otros usuarios los descarguen (si los permisos lo permiten).

Esto no es un problema para muchos sistemas de administración de archivos que podemos comprar, pero ninguno que pueda encontrar se integrará con su sistema de inicio de sesión actual.El cliente solo quiere que los usuarios inicien sesión una vez para acceder a su CP de usuario y a sus archivos.Hasta donde puedo ver, nuestra única opción es crear nosotros mismos una interfaz de administración de archivos.

¿Cuáles son algunas de las opciones que tenemos para permitir cargas usando PHP?Entiendo que necesitamos aumentar el límite de carga de php, pero ¿hay un límite que permitirá php/apache?

Es probable que los archivos tengan un límite de aproximadamente 150 MB si eso es relevante; sin embargo, puede haber situaciones en las que el tamaño de los archivos sea mayor.

Además, ¿qué se debe y qué no se debe hacer al cargar/controlar archivos en un servidor Linux?

Supongo que no tengo preguntas realmente "específicas", pero me gustaría recibir algún consejo sobre por dónde empezar y algunos de los obstáculos típicos con los que nos encontraremos.

¿Fue útil?

Solución

En realidad, la gestión de archivos es bastante sencilla.Aquí hay algunas sugerencias que pueden indicarle la dirección correcta.

En primer lugar, si se trata de una situación de servidor web con carga equilibrada, necesitará aumentar un poco la complejidad para poder colocar los archivos en un lugar común.Si ese es el caso, envíeme un ping y estaré encantado de enviarle nuestro servidor/cliente de archivos superligero que utilizamos para la misma situación.

Hay algunas variables que querrás modificar para permitir cargas más grandes.Recomiendo usar directivas de Apache para limitar estos cambios a un archivo en 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>

Arquitectura:

Cree una tabla de base de datos que almacene información sobre cada archivo.

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 

Qué es Owner_Field y Owner_Key?Una forma sencilla de decir a qué "entidad" pertenece el archivo.En este caso específico, se cargaron varios tipos de archivos.En tu caso, un simple User_ID campo puede ser adecuado.

El propósito de almacenar al propietario es que usted pueda restringir quién puede descargar y eliminar el archivo.Eso será crucial para proteger las descargas.

Aquí hay una clase de muestra. que se puede utilizar para aceptar la carga de archivos desde el navegador.Por supuesto, tendrás que modificarlo para adaptarlo.

Hay algunas cosas a tener en cuenta sobre el siguiente código.Dado que se utiliza con un servidor de aplicaciones y un servidor de archivos, hay algunas cosas que "reemplazar".

  1. Cualquier ocurrencia de App::CallAPI(...) Será necesario reemplazarlo con una consulta o un conjunto de consultas que hagan "lo mismo".
  2. Cualquier ocurrencia de App::$FS->... deberá ser reemplazado con las funciones correctas de manejo de archivos en PHP, como move_uploaded_file, readfile, etc...

Aquí lo tienes.Tenga en cuenta que aquí hay funciones que le permiten ver archivos propiedad de un usuario determinado, eliminar archivos, etc., etc.Más explicación al final...

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

Tenga en cuenta que esta clase NO implementa seguridad.Se supone que la persona que llama tiene un Owner_Field y Owner_Key autenticados antes de llamar. FileClient::Serve(...) etc...

Es un poco tarde, así que si algo de esto no tiene sentido, deja un comentario.Que tengas una buena tarde y espero que esto ayude en algo.

PD.La interfaz de usuario puede consistir en tablas simples y campos de carga de archivos, etc.O podrías ser elegante y usar un cargador flash...

Otros consejos

Te recomiendo echar un vistazo a los siguientes ejemplos de código de CakePHP aportados por la comunidad:

aquí es buena opción. Se requiere instalar un cliente de PC y un solo servidor de archivos php. Sin embargo, su ejecución es rápida!

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top