PHP文件管理系统

发布于 2024-07-25 18:52:55 字数 470 浏览 8 评论 0原文

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

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

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

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

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

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

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

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

We need to create a file management interface that integrates with the clients current website built on cakephp.

The file manager must only let the users see the files that they have permissions too.

The user will be able to upload files(of any size) and have other users download those files (if permissions allow).

This is no problem for many file management systems that we can purchase but none that I can find will integrate with their current log in system. The client only wants the users to log in once to access their user CP and their files. So as far as I can see our only option is to build a file management interface ourselves.

What are some of the options that we have to allow uploads using PHP? I understand that we need to increase the php upload limit, but is there a ceiling that php/apache will allow?

The files will likely cap out at approximately 150MB if that is relevant, however there may be situations where the file sizes will be larger.

Also what are the do's and don'ts of file upload/control on a Linux server?

I suppose I have no real 'specific' questions but would like some advise on where to start and some of the typical pitfalls we will run into.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

固执像三岁 2024-08-01 18:52:55

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

首先,如果这是负载平衡的 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_filereadfile< /code> 等...

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

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

}

注释:

请记住,此类不实现安全性。 它假设调用者在调用 FileClient::Serve(...) 等之前拥有经过身份验证的 Owner_Field 和 Owner_Key...

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

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

File management is quite easy, actually. Here are some suggestions that may point you in the right direction.

First of all, if this is a load balanced web server situation, you'll need to step up the complexity a little in order to put the files in one common place. If that's the case, ping me and I'll be happy to send you our super-light file server/client we use for that same situation.

There are a few variables you will want to affect in order to allow larger uploads. I recommend using apache directives to limit these changes to a particular file:

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

Architecture:

Create a database table that stores some information about each file.

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 

What is Owner_Field and Owner_Key? A simple way to say what "entity" owns the file. In this specific case there were multiple types of files being uploaded. In your case, a simple User_ID field may be adequate.

The purpose of storing the owner is so that you can restrict who can download and delete the file. That will be crucial for protecting the downloads.

Here is a sample class that can be used to accept the file uploads from the browser. You'll need to modify it to suit, of course.

There are a few things to note about the following code. Since this is used with an Application Server and a File Server, there are a few things to "replace".

  1. Any occurrences of App::CallAPI(...) will need to be replaced with a query or set of queries that do the "same thing".
  2. Any occurrences of App::$FS->... will need to be replaced with the correct file handling functions in PHP such as move_uploaded_file, readfile, etc...

Here it is. Keep in mind that there are functions here which allow you to see files owned by a given user, delete files, and so on and so forth. More explanation at the bottom...

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

}

Notes:

Please keep in mind that this class DOES NOT implement security. It assumes that the caller has an authenticated Owner_Field and Owner_Key before calling FileClient::Serve(...) etc...

It's a bit late, so if some of this doesn't make sense, just leave a comment. Have a great evening, and I hope this helps some.

PS. The user interface can be simple tables and file upload fields, etc.. Or you could be fancy and use a flash uploader...

你爱我像她 2024-08-01 18:52:55

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

I recommend having a look at the following community-contributed CakePHP code examples:

余生共白头 2024-08-01 18:52:55

这是不错的选择。 它需要您安装 PC 客户端和单文件 php 服务器。 但跑得很快!

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

here is good choice. It requires you install a PC client and a single file php server. But it runs fast!

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文