financial-services dry-run模式:部署前校验POST请求体的正确姿势
2026/9/15 18:18:42
在能源化工行业的生产现场,视频监控系统每天都会产生海量的视频数据。这些视频文件通常具有以下特点:
传统的HTTP上传方式经常遇到以下问题:
| 技术方案 | 优点 | 缺点 |
|---|---|---|
| 原生HTML5 | 无需插件 | 兼容性差 |
| Flash上传 | 兼容性好 | 安全性低 |
| WebUploader | 支持分片/断点续传 | 需要额外配置 |
最终选择WebUploader的原因:
[浏览器端] WebUploader → [网络] → [服务端] Nginx → PHP → 存储集群关键参数配置:
var uploader = WebUploader.create({ swf: 'Uploader.swf', server: '/upload.php', pick: '#filePicker', chunked: true, chunkSize: 2 * 1024 * 1024, threads: 3, formData: { uid: '设备ID' } });// 分片上传前 uploader.on('uploadBeforeSend', function(block, data) { data.md5 = uploader.md5File(block.file); }); // 上传进度 uploader.on('uploadProgress', function(file, percentage) { $('#progress').text(percentage * 100 + '%'); });$chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0; $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0; $fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : ''; // 临时分片文件路径 $tempDir = 'uploads/tmp_' . $_POST['uid']; $filePath = $tempDir . '/' . $fileName . '.part' . $chunk; if (!is_dir($tempDir)) { mkdir($tempDir, 0777, true); } move_uploaded_file($_FILES['file']['tmp_name'], $filePath);if ($chunk == $chunks - 1) { $finalPath = 'uploads/' . date('Ym') . '/' . $fileName; if (!is_dir(dirname($finalPath))) { mkdir(dirname($finalPath), 0777, true); } $out = fopen($finalPath, "wb"); for ($i = 0; $i < $chunks; $i++) { $partPath = $tempDir . '/' . $fileName . '.part' . $i; $in = fopen($partPath, "rb"); while ($buff = fread($in, 4096)) { fwrite($out, $buff); } fclose($in); unlink($partPath); } fclose($out); rmdir($tempDir); }在php.ini中调整:
upload_max_filesize = 2G post_max_size = 2G memory_limit = 256M max_execution_time = 3600// check接口实现 $fileList = glob($tempDir.'/*.part*'); $uploadedChunks = array_map(function($v){ return intval(substr($v, strrpos($v, 'part') + 4)); }, $fileList); echo json_encode($uploadedChunks);| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 分片上传失败 | 临时目录权限不足 | chmod -R 777 uploads |
| 合并后文件损坏 | 分片顺序错乱 | 检查$chunk参数传递 |
| 上传速度慢 | 厂区网络限速 | 调整chunkSize为5MB |
exec("ffmpeg -i input.mp4 -vf 'drawtext=text='设备1_'.strftime('%Y%m%d'):x=10:y=10' output.mp4");exec("ffmpeg -i input.mov -c:v libx264 -preset fast -crf 22 output.mp4");在厂区典型网络环境下(10Mbps带宽,200ms延迟):
| 文件大小 | 传统方式 | 分片上传 | 提升效果 |
|---|---|---|---|
| 500MB | 15分钟 | 8分钟 | 46% |
| 1GB | 失败 | 18分钟 | 100% |
| 2GB | 失败 | 35分钟 | 100% |
$allowed = ['video/mp4', 'video/avi']; if (!in_array($_FILES['file']['type'], $allowed)) { die('Invalid file type'); }exec("clamscan --no-summary ".escapeshellarg($tempPath), $output, $return); if ($return !== 0) { unlink($tempPath); die('Virus detected'); }location /upload { proxy_pass http://upload_cluster; client_max_body_size 2G; proxy_read_timeout 3600s; }$thumbCmd = "ffmpeg -i {$finalPath} -ss 00:00:05 -vframes 1 {$thumbPath}"; exec($thumbCmd);// 上传完成后触发SCADA事件 $scadaData = [ 'device_id' => $_POST['uid'], 'video_path' => $finalPath, 'timestamp' => time() ]; $context = stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => 'Content-Type: application/json', 'content' => json_encode($scadaData) ] ]); file_get_contents('http://scada/api/event', false, $context);