设为首页收藏本站
天天打卡

 找回密码
 立即注册
搜索
查看: 34|回复: 13

JavaScript+PHP实现视频文件分片上传的示例代码

[复制链接]

2

主题

43

回帖

130

积分

注册会员

积分
130
发表于 2024-4-20 08:19:02 | 显示全部楼层 |阅读模式
目录


摘要

视频文件分片上传,整体思路是利用JavaScript将文件切片,然后循环调用上传接口
  1. upload.php
复制代码
将切片上传到服务器。这样将由原来的一个大文件上传变为多个小文件同时上传,节省了上传时间,这就是文件分片上传的其中一个好处。


上代码

index.html
通过前端将文件对象切分成多个小块,然后依次将这些小块的文件对象上传到服务器。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3.         <head>
  4.                 <meta charset="UTF-8">
  5.                 <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.                 <title>视频文件分片上传</title>
  7.                 <style>
  8.                     *{
  9.                         padding: 0;
  10.                         margin: 0;
  11.                     }
  12.                     .title {
  13.                         text-align: center;
  14.                         font-size: 25px;
  15.                         margin-top: 50px;
  16.                     }
  17.                     .video_upload {
  18.                         width: 500px;
  19.                         height: 60px;
  20.                         background: #eee;
  21.                         margin: 30px auto 0;
  22.                         border: 2px dashed #ccc;
  23.                         border-radius: 10px;
  24.                         position: relative;
  25.                         cursor: pointer;
  26.                         text-align: center;
  27.                         font-size: 25px;
  28.                         line-height: 60px;
  29.                         color: #666;
  30.                     }
  31.                     #fileInput {
  32.                         width: 100%;
  33.                         height: 100%;
  34.                         position: absolute;
  35.                         left: 0;
  36.                         top: 0;
  37.                         opacity: 0;
  38.                         cursor: pointer;
  39.                     }
  40.                     #uploadButton {
  41.                         width: 130px;
  42.                         height: 40px;
  43.                         border: none;
  44.                         outline: none;
  45.                         border-radius: 10px;
  46.                         font-size: 17px;
  47.                         margin: 10px auto;
  48.                     }
  49.                     #ret {
  50.                         text-align: center;
  51.                         font-size: 16px;
  52.                         margin-top: 20px;
  53.                     }
  54.                     #ret video {
  55.                         width: 450px;
  56.                     }
  57.                 </style>
  58.         </head>
  59.         <body>
  60.             
  61.         <p class="title">javaScript+PHP实现视频文件分片上传</p>
  62.         <div class="video_upload">
  63.             <span class="text"> + </span>
  64.             <input type="file" id="fileInput" accept="video/*">
  65.         </div>
  66.                 <button id="uploadButton" style="display:none;">开始上传</button>
  67.                 <p id="ret"></p>

  68.                 <script>
  69.                
  70.                         // 定义全局变量
  71.                         let videoFile = null;
  72.                         let chunkSize = 1024 * 1024; // 1MB 分片大小
  73.                        
  74.                         // 当文件选择框的值改变时触发该函数
  75.                         function handleFileSelect(event) {
  76.                             const fileList = event.target.files;
  77.                             if (fileList.length > 0) {
  78.                                 videoFile = fileList[0];
  79.                                 console.log("选择了文件: ", videoFile.name);
  80.                                 document.querySelector('.video_upload .text').textContent = videoFile.name;
  81.                                 document.querySelector('#uploadButton').style.display = 'block';
  82.                             }
  83.                         }
  84.                        
  85.                         // 分片并上传文件
  86.                         async function uploadFile() {
  87.                             if (!videoFile) {
  88.                                 console.error("请选择一个视频文件");
  89.                                 return;
  90.                             }
  91.                        
  92.                             const fileSize = videoFile.size;
  93.                             let start = 0;
  94.                             let end = Math.min(chunkSize, fileSize);
  95.                             let chunkIndex = 0;
  96.                        
  97.                             // 获取文件名
  98.                             const fileName = videoFile.name;
  99.                        
  100.                             while (start < fileSize) {
  101.                                 const chunk = videoFile.slice(start, end); // 从文件中截取一个分片
  102.                        
  103.                                 // 使用FormData来构建multipart/form-data格式的请求体
  104.                                 const formData = new FormData();
  105.                                 formData.append('file', chunk);
  106.                                 formData.append('chunkIndex', chunkIndex);
  107.                                 formData.append('fileName', fileName); // 将文件名作为 formData 的一部分
  108.                        
  109.                                 try {
  110.                                     const response = await fetch('upload.php', {
  111.                                         method: 'POST',
  112.                                         body: formData
  113.                                     });
  114.                        
  115.                                     if (!response.ok) {
  116.                                         throw new Error('上传失败');
  117.                                     }
  118.                        
  119.                                     console.log('上传分片 ', chunkIndex, ' 成功');
  120.                                 } catch (error) {
  121.                                     console.error('上传分片 ', chunkIndex, ' 失败: ', error.message);
  122.                                     return;
  123.                                 }
  124.                        
  125.                                 start = end;
  126.                                 end = Math.min(start + chunkSize, fileSize);
  127.                                 chunkIndex++;
  128.                             }
  129.                        
  130.                             console.log('文件上传完成');
  131.                        
  132.                             // 上传完成后发送通知给服务器进行合并
  133.                             notifyServerForMerge(fileName);
  134.                         }
  135.                        
  136.                         // 发送通知给服务器进行合并
  137.                         async function notifyServerForMerge(fileName) {
  138.                             try {
  139.                                 const response = await fetch('merge_chunks.php', {
  140.                                     method: 'POST',
  141.                                     headers: {
  142.                                         'Content-Type': 'application/json'
  143.                                     },
  144.                                     body: JSON.stringify({ fileName: fileName })
  145.                                 });
  146.                        
  147.                                 if (!response.ok) {
  148.                                     throw new Error('无法通知服务器进行合并');
  149.                                 }
  150.                                 
  151.                                 const res_data = await response.json();
  152.                        
  153.                                 console.log('已通知服务器进行合并');
  154.                                 document.querySelector('.video_upload .text').textContent = '分片合并完成!';
  155.                                 document.querySelector('#ret').innerHTML = '<video autoplay controls src="'+res_data.filePath+'"></video>';
  156.                                 document.querySelector('#uploadButton').style.display = 'none';
  157.                             } catch (error) {
  158.                                 console.error('通知服务器进行合并时发生错误: ', error.message);
  159.                             }
  160.                         }
  161.                        
  162.                         // 注册文件选择框的change事件
  163.                         document.getElementById('fileInput').addEventListener('change', handleFileSelect);
  164.                        
  165.                         // 注册上传按钮的click事件
  166.                         document.getElementById('uploadButton').addEventListener('click', uploadFile);
  167.                 </script>

  168.         </body>
  169. </html>
复制代码
upload.php
这个是用于接收前端传过来的每一段分片,然后上传到
  1. uploads
复制代码
文件夹,上传之后就是一段一段的小分片。
  1. <?php

  2.     // 设置允许跨域访问
  3.     header("Access-Control-Allow-Origin: *");
  4.     header("Access-Control-Allow-Methods: POST");
  5.    
  6.     // 检查是否接收到文件和分片索引
  7.     if (isset($_FILES['file']['error']) && isset($_POST['chunkIndex']) && isset($_POST['fileName'])) {
  8.         
  9.         $error = $_FILES['file']['error'];
  10.         $chunkIndex = $_POST['chunkIndex'];
  11.         $fileName = $_POST['fileName']; // 获取文件名
  12.         
  13.         // 检查是否有错误
  14.         if ($error !== UPLOAD_ERR_OK) {
  15.             http_response_code(500);
  16.             echo json_encode(array(
  17.                 'error' => '文件上传失败'
  18.             ));
  19.             exit();
  20.         }
  21.         
  22.         // 设置存储目录和文件名
  23.         $uploadDir = './uploads/';
  24.         $filePath = $uploadDir . $fileName . '.' . $chunkIndex;
  25.         
  26.         // 将分片移动到指定的目录
  27.         if (move_uploaded_file($_FILES['file']['tmp_name'], $filePath)) {
  28.             
  29.             echo json_encode(array(
  30.                 'success' => '分片上传成功'
  31.             ));
  32.         } else {
  33.             
  34.             http_response_code(500);
  35.             echo json_encode(array(
  36.                 'error' => '分片上传失败'
  37.             ));
  38.         }
  39.     } else {
  40.         
  41.         http_response_code(400);
  42.         echo json_encode(array(
  43.             'error' => '缺少文件、分片索引或文件名'
  44.         ));
  45.     }
  46.    
  47. ?>
复制代码
merge_chunks.php
这个是用来合并分片的,当前端完成上传分片的操作,前端会异步告诉服务器你已经完成所有分片的上传,接下来将每个分片名告诉合并程序完成所有分片的合并,合并之后就是一个完整的视频文件。
  1. <?php

  2.     // 设置允许跨域访问
  3.     header("Access-Control-Allow-Origin: *");
  4.     header("Access-Control-Allow-Methods: POST");
  5.     header("Content-Type: application/json");
  6.    
  7.     // 获取请求体中的文件名
  8.     $data = json_decode(file_get_contents("php://input") , true);
  9.     $fileName = isset($data['fileName']) ? $data['fileName'] : null;
  10.     if ($fileName) {
  11.         
  12.         $uploadDir = './uploads/';
  13.         $finalFilePath = $uploadDir . $fileName;
  14.         $totalChunks = count(glob($uploadDir . $fileName . '.*'));
  15.         
  16.         // 检查是否所有分片都已上传
  17.         if ($totalChunks > 0) {
  18.             
  19.             // 所有分片都已上传,开始合并
  20.             $finalFile = fopen($finalFilePath, 'wb');
  21.             
  22.             // 逐个读取分片并写入最终文件
  23.             for ($i = 0; $i < $totalChunks; $i++) {
  24.                 $chunkFilePath = $uploadDir . $fileName . '.' . $i;
  25.                 $chunkFile = fopen($chunkFilePath, 'rb');
  26.                 stream_copy_to_stream($chunkFile, $finalFile);
  27.                 fclose($chunkFile);
  28.                 unlink($chunkFilePath); // 删除已合并的分片
  29.                
  30.             }
  31.             
  32.             fclose($finalFile);
  33.             http_response_code(200);
  34.             echo json_encode(array(
  35.                 'success' => '文件合并成功',
  36.                 'filePath' => $finalFilePath
  37.             ));
  38.         } else {
  39.             
  40.             http_response_code(400);
  41.             echo json_encode(array(
  42.                 'error' => '没有上传的分片'
  43.             ));
  44.         }
  45.     } else {
  46.         
  47.         http_response_code(400);
  48.         echo json_encode(array(
  49.             'error' => '缺少文件名'
  50.         ));
  51.     }
  52. ?>
复制代码
程序目录

请自行创建
  1. uploads
复制代码
目录。

以上就是JavaScript+PHP实现视频文件分片上传的示例代码的详细内容,更多关于JavaScript+PHP视频文件上传的资料请关注脚本之家其它相关文章!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 打卡月天数:0
  • 打卡总奖励:93
  • 最近打卡:2024-09-19 09:19:04

0

主题

84

回帖

311

积分

中级会员

积分
311
发表于 2024-4-30 01:35:14 | 显示全部楼层
我想了解更多

2

主题

56

回帖

152

积分

注册会员

积分
152
发表于 2024-5-21 20:00:46 | 显示全部楼层
这个话题真是有趣,我也对它感兴趣。

0

主题

43

回帖

87

积分

注册会员

积分
87
发表于 2024-5-22 23:34:40 | 显示全部楼层
6666666666

3

主题

50

回帖

168

积分

注册会员

积分
168
发表于 2024-6-15 22:23:25 | 显示全部楼层
谢谢你分享这个信息

3

主题

49

回帖

165

积分

注册会员

积分
165
发表于 2024-7-3 04:42:25 | 显示全部楼层
你的信息来源是?我想了解更多。

1

主题

64

回帖

152

积分

注册会员

积分
152
发表于 2024-7-16 18:22:49 | 显示全部楼层
我想了解更多

1

主题

44

回帖

110

积分

注册会员

积分
110
发表于 2024-8-3 13:32:36 | 显示全部楼层
太棒了!感谢分享这个信息!

2

主题

38

回帖

122

积分

注册会员

积分
122
发表于 2024-8-14 00:02:14 | 显示全部楼层
6666666666

0

主题

70

回帖

140

积分

注册会员

积分
140
发表于 2024-10-6 08:32:32 | 显示全部楼层
顶一个,观点非常中肯!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|爱云论坛 - d.taiji888.cn - 技术学习 免费资源分享 ( 蜀ICP备2022010826号 )|天天打卡

GMT+8, 2024-11-28 04:09 , Processed in 0.118946 second(s), 27 queries .

Powered by i云网络 Licensed

© 2023-2028 正版授权

快速回复 返回顶部 返回列表