文件上传工具:Tiny File Manager

Tiny File Manager的意外惊喜,支持URL下载。

Axure Cloud私域是在Windows环境上运行,因为一些原因,要切换到Ubuntu上,就不能使用了。Axure原型协作另说,但原型的浏览就是个问题了。发现php文件上传工具Tiny File Manager挺合适的,小巧只有单个文件,支持多用户与隔离效果;当然只有上传,浏览由Nginx负责,不会限制,是优点也是缺点,但敌不过合适现有使用场景。

Tiny File Manager

下载,使用时要注意,需要能正常连接这些域名:(国内没有问题)

  • cdn.datatables.net
  • cdn.jsdelivr.net
  • cdnjs.cloudflare.com
  • code.jquery.com
Bash
# webRoot 目录要能让 www-data 读和写。
webRoot=/www/rpFiles
wget https://github.com/prasathmani/tinyfilemanager/archive/refs/heads/master.zip
7za x master.zip
mv ./tinyfilemanager-master/tinyfilemanager.php ${webRoot}/index.php
mv ./tinyfilemanager-master/translation.json  ${webRoot}/

vim ${webRoot}/index.php

  • 修改好了,做备份:sudo 7za a /data/rpFiles.7z ${webRoot}/index.php ${webRoot}/translation.json ${webRoot}/favicon.ico
  • 以下内容在前150行里,更多配置项见这里

改默认为中文

PHP
$CONFIG = '{"lang":"zh-CN","error_reporting":false,"show_hidden":false,"hide_Cols":false,"theme":"light"}';

修改用户名与密码,密码hash值生成见备注

PHP
// Generate secure password hash - https://tinyfilemanager.github.io/docs/pwd.html
$auth_users = array(
    'admin' => '$2y$10$lm4Z68/ZewnUD.k9fPqoj.i3xfo/KA.FthzIj7Vy01/83W',
    'user' => '$2y$10$WRmAkBy7ug7LpS.0VSEBfe3OTH28qUxluRUgVoDvLCNqYc5HfcmuC' // User@12345
);

用户主目录隔离

  • 需要在${webRoot}目录下创建adminDIR和userDIR子目录
  • URL也是 http://rp.t725.cn/adminDIR/
  • 不要填错,错了登录报错;也不要填绝对路径,链接会有问题。
PHP
// user specific directories
// array('Username' => 'Directory path', 'Username2' => 'Directory path', ...)
$directories_users = array(
    'admin' => 'adminDIR',
    'user' => 'userDIR'
);

改时区与时间格式,默认的不适合我们中文习惯

PHP
// Default timezone for date() and time()
// Doc - http://php.net/manual/en/timezones.php
$default_timezone = 'Asia/Shanghai'; // UTC
// date() format for file modification date
// Doc - https://www.php.net/manual/en/function.date.php
$datetime_format = 'Y-m-d H:i:s';

在线文档查看改为microsoft

PHP
// Online office Docs Viewer
// Available rules are 'google', 'microsoft' or false
// Google => View documents using Google Docs Viewer
// Microsoft => View documents using Microsoft Web Apps Viewer
// false => disable online doc viewer
$online_viewer = 'microsoft';

最大上传文件,调整与php的 upload_max_filesize 值一样,

  • upload_max_filesize不调整的话,会被 upload_chunk_size_bytes 配置,绕过php与nginx的上传文件大小限制。
    • 但实测还是不受upload_max_filesize约束。
PHP
// Maximum file upload size
// Increase the following values in php.ini to work properly
// memory_limit, upload_max_filesize, post_max_size
$max_upload_size_bytes = 5242880; // size 5,242,880 bytes (5MB)

// chunk size used for upload
// eg. decrease to 1MB if nginx reports problem 413 entity too large
$upload_chunk_size_bytes = 1048576; // chunk size 1,048,576 bytes (1MB)

其他的配置项,可以不改。

PHP
// Enable ace.js (https://ace.c9.io/) on view's page
$edit_files = true;
// 不能动
$iconv_input_encoding = 'UTF-8'; 
// 不配置的话,就直接上传 /favicon.ico 文件。
$favicon_path = '';
// 默认为"";配置允许创建/重命名的文件扩展名。例如:'html,css,js'
$allowed_file_extensions = '';
// 默认为"";配置允许上传的文件扩展名。例如:'jpg,png,pdf,gif,html,css,js' 
$allowed_upload_extensions = '';

Nginx

先http,再https:/etc/nginx/sites-enabled/rp.t725.cn.conf

Nginx
server {
    listen       80;
    server_name  rp.t725.cn;

    # access_log 按月+域名生成文件
    if ($time_iso8601 ~ "^\d{2}(\d{2})-(\d{2})") {
        set $YY $1;
        set $MM $2;
    }
    access_log /data/www/log/nginx_${YY}${MM}_${host}.log main;

    root   /data/www/rpFiles;
    index  start.html index.php;
    client_max_body_size 5m; # 上传文件大小上限
    add_header X-Frame-Options SAMEORIGIN; # 只允许同源域名下 frame 来嵌套
    add_header X-XSS-Protection "1; mode=block"; # 防止 XSS
    add_header X-Content-Type-Options nosniff; # 禁止嗅探 MIME 类型

    if ($http_user_agent = -) { return 444; }
    if ($http_user_agent = "") { return 444; }
    #location ^~ /. { return 444; } # 非法的URI请求

    # php-fpm [~ 区分大小写 ~* 不区分大小写],注意:不能使用见的[~ \.php$],否则上传php文件,被访问时会执行。
    location ^~ /index.php {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
    location / {
        try_files $uri $uri/ =404;
    }
}

数据备份与空间大小检查脚本

Bash
#!/bin/bash
# /root/rpFiles_Abnormal.sh 
# update by 25/11/14,后续不再与生产环境的内容同步
# 需要以root账号运行,且 webRoot 不要含有空格和/结尾。
webRoot=/data/rpFiles
bakRoot=/data/BAK
abnormalLog=${bakRoot}/rpFiles_Abnormal.log

# 删除指定find条件的文件,调用格式:abnormalCheck 目录 "find条件" "条件描述"
function abnormalCheck {
    local aC_DIR=$1
    local aC_Condition=$2
    local aC_Text=$3
    if [ ! -d ${aC_DIR} ]; then return 1; fi

    local FileQty=$(find ${aC_DIR} ${aC_Condition} | wc -l)
    echo -e "\n=== $(date '+%Y-%m-%d %H:%M:%S') 找到${aC_Text}的文件数量:${FileQty}\n\tfind ${aC_DIR} ${aC_Condition} | wc -l"
    if [ ${FileQty} -eq 0 ]; then return 0; fi    
    echo ===== $(date '+%Y-%m-%d %H:%M:%S') 找到${aC_Text}的文件 ===== >> ${abnormalLog}
    echo 删除前: >> ${abnormalLog}
    find ${aC_DIR} ${aC_Condition} -exec echo {} >> ${abnormalLog} \;
    find ${aC_DIR} ${aC_Condition} -delete
    echo 删除后: >> ${abnormalLog}
    find ${aC_DIR} ${aC_Condition} -exec echo {} >> ${abnormalLog} \;
    echo ===== $(date '+%Y-%m-%d %H:%M:%S') 结束 ===== >> ${abnormalLog}
}

# 统计目录大小,且删除大于5M文件。调用格式:subDirectoryCheck 目录
function subDirectoryCheck {    
    local targetDIR=$1
    if [ ! -d ${targetDIR} ]; then return 1; fi

    local lastName=$(basename ${targetDIR})
    local logFileName=_statistics_${lastName}.log
    if [ ! -f ${targetDIR}/${logFileName} -o ! -s ${targetDIR}/${logFileName} ]; then
        rm -f ${targetDIR}/${logFileName}
        echo "$(date '+%Y-%m-%d %H:%M:%S') 创建" > ${targetDIR}/${logFileName}
    fi       

    local actualSize=$(du -sm ${targetDIR} | awk '{print $1}') # 以MB为单位,获取实际大小
    local fileCount=$(find ${targetDIR} -mindepth 1 -not -type d | wc -l) # 获取文件数量
    # 查找当前目录下,大于5M文件;可使用 truncate -s 6M test.file 生成测试文件
    local bigFileQty=$(find ${targetDIR} -type f -size +5M | wc -l)
    local outText="=== $(date '+%Y-%m-%d %H:%M:%S') ${lastName}总共${fileCount}个文件,总共${actualSize}MB(自动删除大于5M的文件数:${bigFileQty})"
    echo -e "${outText}\n\t${targetDIR}/${logFileName}"
    sed -i '1i\'"${outText}" ${targetDIR}/${logFileName} # 将内容插入到第1行的前面,注意变量引用方式,"1i\${outText}"是无效的。'
    if [ ${bigFileQty} -eq 0 ]; then return 0; fi 
    find ${targetDIR} -type f -size +5M -exec sed -i "1i\{}" ${targetDIR}/${logFileName} \;
    find ${targetDIR} -type f -size +5M -delete
    sed -i "s|${targetDIR}||" ${targetDIR}/${logFileName} # 替换targetDIR为空

    # 目录总大小是不是超过512MB
    actualSize=$(du -sm ${targetDIR} | awk '{print $1}') 
    if [ ${actualSize} -gt 512 ]; then
        echo "== $(date '+%Y-%m-%d %H:%M:%S') ${targetDIR}目录总共${actualSize}MB" >> ${abnormalLog}
    fi 
}

# 目录文件备份,调用格式:subDirectoryBackups 目录
function subDirectoryBackups {
    local targetDIR=$1
    if [ ! -d ${targetDIR} ]; then return 1; fi

    if [ ! -d ${bakRoot}/rpFiles ]; then mkdir -p ${bakRoot}/rpFiles; fi
    local bakTarName=$(basename ${targetDIR}).tar.gz
    local bakFile=${bakRoot}/rpFiles/${bakTarName}
    # 没有24小时内的备份文件,就执行备份
    local checkFile=$(find ${bakRoot}/rpFiles -maxdepth 1 -type f -name ${bakTarName} -mtime 0)
    echo -e "\nfind ${bakRoot}/rpFiles -maxdepth 1 -type f -name ${bakTarName} -mtime 0 : ${checkFile}"
    if [ -z ${checkFile} ]; then # checkFile 可能有值,也可能为空;空才需要执行备份。
        rm -f ${bakFile}
        tar -czf ${bakFile} -C ${targetDIR} .
        echo == $(date '+%Y-%m-%d %H:%M:%S') ${bakFile} 
    fi
}
# 导出函数与变量,多个使用空格间隔,给find的子shell使用;未导出的,在子shell中函数不能使用,变量为空值。
export -f subDirectoryCheck
export -f subDirectoryBackups
export webRoot bakRoot abnormalLog
abnormalCheck ${webRoot} "-not -type d -perm /111" "有执行权限"
# 实际测试发现,不能排除sh以root创建的_statistics_*.log文件,被注释
#abnormalCheck ${webRoot} '-not -type d -not -user nginx -not -name \"_statistics_*.log\"' "不是nginx用户"
find ${webRoot} -maxdepth 1 -mindepth 1 -type d -exec bash -c 'subDirectoryCheck "$0"' {} \;
find ${webRoot} -maxdepth 1 -mindepth 1 -type d -exec bash -c 'subDirectoryBackups "$0"' {} \;
# find输出内容示例:(-maxdepth 1 -mindepth 1 在输出中,排除了 ${webRoot} 目录本身这一行。)
#/data/rpFiles/std
#/data/rpFiles/xxx
exit

定时任务

Bash
sudo crontab -e
# 0 */6 * * * /usr/bin/sh /root/rpFiles_Abnormal.sh

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注