我们需要创建一个文件管理界面,与客户当前基于 cakephp 构建的网站集成。

文件管理器必须只让用户看到他们也有权限的文件。

用户将能够上传文件(任何大小)并让其他用户下载这些文件(如果权限允许)。

对于我们可以购买的许多文件管理系统来说,这不是问题,但我发现没有一个能够与他们当前的登录系统集成。客户端只希望用户登录一次即可访问其用户 CP 及其文件。据我所知,我们唯一的选择是自己构建一个文件管理界面。

我们必须允许使用 PHP 上传的选项有哪些?我知道我们需要增加 php 上传限制,但是 php/apache 是否允许上限?

如果相关的话,文件的上限可能约为 150MB,但在某些情况下文件大小可能会更大。

另外,在 Linux 服务器上上传/控制文件的注意事项是什么?

我想我没有真正的“具体”问题,但希望获得一些关于从哪里开始以及我们将遇到的典型陷阱的建议。

有帮助吗?

解决方案

实际上,文件管理非常简单。以下是一些可能为您指明正确方向的建议。

首先,如果这是负载平衡的 Web 服务器情况,您需要稍微提高复杂性,以便将文件放在一个公共位置。如果是这种情况,请联系我,我很乐意向您发送我们用于相同情况的超轻型文件服务器/客户端。

为了允许更大的上传,您需要影响一些变量。我建议使用 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_FieldOwner_Key?一种简单的方式来说明哪个“实体”拥有该文件。在这种特定情况下,上传了多种类型的文件。对于你的情况,一个简单的 User_ID 场可能就足够了。

存储所有者的目的是为了限制谁可以下载和删除该文件。这对于保护下载至关重要。

这是一个示例类 可用于接受从浏览器上传的文件。当然,您需要对其进行修改以适应。

下面的代码有几点需要注意。由于它与应用程序服务器和文件服务器一起使用,因此有一些东西需要“替换”。

  1. 任何出现以下情况 App::CallAPI(...) 需要替换为执行“相同操作”的一个查询或一组查询。
  2. 任何出现以下情况 App::$FS->... 需要用 PHP 中正确的文件处理函数替换,例如 move_uploaded_file, readfile, , ETC...

这里是。请记住,这里有一些功能可以让您查看给定用户拥有的文件、删除文件等等。更多解释在底部...

<?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(...) ETC...

有点晚了,所以如果其中有些内容没有意义,请发表评论。祝您度过一个愉快的夜晚,希望这对一些人有所帮助。

附言。用户界面可以是简单的表格和文件上传字段等。或者你也可以使用 Flash 上传器......

其他提示

我建议查看以下社区贡献的 CakePHP 代码示例:

这里是很好的选择。它需要你安装PC客户端和一个单一的文件PHP服务器。但它跑得快!

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top