H5前端上传视频的Java转PHP实现方案

在现代Web应用中,H5前端视频上传是常见需求,而服务端语言从Java迁移到PHP时,需要确保上传功能的平滑过渡。以下实现方案涵盖了前后端的关键技术点。

前端H5视频上传实现

前端采用HTML5的<input type="file">结合FormData实现:

<input type="file" id="videoUpload" accept="video/*">
<button onclick="uploadVideo()">上传</button>

<script>
function uploadVideo() {
  const file = document.getElementById('videoUpload').files[0];
  const formData = new FormData();
  formData.append('video', file);
  
  fetch('/api/upload.php', {
    method: 'POST',
    body: formData
  }).then(response => response.json())
    .then(data => console.log(data));
}
</script>
PHP服务端接收处理

PHP端需处理大文件上传和视频信息获取:

<?php
header('Content-Type: application/json');
$targetDir = "uploads/";
$targetFile = $targetDir . basename($_FILES["video"]["name"]);

// 移动临时文件到目标目录
if (move_uploaded_file($_FILES["video"]["tmp_name"], $targetFile)) {
    // 获取视频元数据(需安装ffmpeg)
    $ffmpegPath = '/usr/bin/ffmpeg';
    $cmd = "$ffmpegPath -i $targetFile 2>&1";
    exec($cmd, $output);
    
    $metadata = [];
    foreach($output as $line){
        if(preg_match('/Duration: (\d+:\d+:\d+)/', $line, $matches)){
            $metadata['duration'] = $matches[1];
        }
        if(preg_match('/Video: (.+?),/', $line, $matches)){
            $metadata['video_codec'] = $matches[1];
        }
    }
    
    echo json_encode([
        'status' => 'success',
        'path' => $targetFile,
        'metadata' => $metadata
    ]);
} else {
    echo json_encode(['status' => 'error']);
}
?>
Java到PHP的迁移要点
  1. 文件上传处理差异 Java通常使用MultipartFile接口,而PHP通过$_FILES超全局数组处理。PHP需要显式调用move_uploaded_file()保存文件。

  2. 视频处理工具 Java可能使用Xuggler等库,PHP通常依赖ffmpeg命令行工具。服务器需确保安装:

sudo apt-get install ffmpeg
  1. 配置调整 修改PHP.ini以适应大文件上传:
upload_max_filesize = 1024M
post_max_size = 1024M
max_execution_time = 300
安全增强措施
  1. 文件类型验证:
$allowedTypes = ['video/mp4', 'video/quicktime'];
if(!in_array($_FILES["video"]["type"], $allowedTypes)){
    die(json_encode(['error' => 'Invalid file type']));
}
  1. 文件名安全处理:
$fileName = preg_replace("/[^a-zA-Z0-9\.\-_]/", "", $_FILES["video"]["name"]);
$targetFile = $targetDir . uniqid() . '_' . $fileName;
  1. CSRF防护: 前端需在FormData中添加token:
formData.append('csrf_token', '<?php echo $_SESSION["csrf_token"]; ?>');
性能优化方案
  1. 分片上传支持: 前端将大文件分块,PHP按序接收合并:
// 检查分片是否存在
if(isset($_POST['chunk']) && isset($_POST['chunks'])){
    $chunk = $_POST['chunk'];
    $tempFile = $targetFile . '.part' . $chunk;
    move_uploaded_file($_FILES["video"]["tmp_name"], $tempFile);
    
    // 全部分片上传完成后合并
    if($chunk == $_POST['chunks']-1){
        $out = fopen($targetFile, "wb");
        for($i=0; $i<$chunks; $i++){
            $partFile = $targetFile . '.part' . $i;
            $in = fopen($partFile, "rb");
            while($buff = fread($in, 4096)) fwrite($out, $buff);
            fclose($in);
            unlink($partFile);
        }
        fclose($out);
    }
}
  1. 异步处理机制: 使用消息队列处理视频转码等耗时操作:
// 将任务写入Redis队列
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$taskId = uniqid();
$redis->rPush('video_queue', json_encode([
    'file' => $targetFile,
    'task_id' => $taskId
]));
监控与日志

记录上传过程中的关键事件:

$log = sprintf("[%s] %s: %s (%s)\n", 
    date('Y-m-d H:i:s'), 
    $_SERVER['REMOTE_ADDR'],
    $_FILES["video"]["name"],
    $_FILES["video"]["size"]
);
file_put_contents('upload.log', $log, FILE_APPEND);
Logo

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。

更多推荐