当前位置: 首页 > article >正文

大文件上传,对接阿里oss采用前端分片技术。完成对应需求!

最近做了一个大文件分片上传的功能,记录下

1. 首先是安装阿里云 oss 扩展

composer require aliyuncs/oss-sdk-php

去阿里云 oss 获取配置文件

AccessKey ID = ***
AccessKey Secret = ***
Bucket名称 = ***
Endpoint = ***

2. 前端上传,对文件进行分片

<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action=""><div class="form-group"><label class="control-label col-xs-12 col-sm-2">{:__('选择本地文件')}:</label><div class="col-xs-12 col-sm-8"><input type="file" id="fileInput"><div><a href="#" onclick="startUpload()"><i class="fa fa-upload"></i>选择完点击上传(请等待上传完成)</a></div><div id="progress" style="margin-top:10px;"></div></div></div><div class="form-group layer-footer"><label class="control-label col-xs-12 col-sm-2"></label><div class="col-xs-12 col-sm-8"><button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button></div></div>
</form><script>let chunkSize = 5 * 1024 * 1024; // 分片大小5MBlet uploadId = '';let objectName = '';let parts = [];const CHUNK_SIZE = 5 * 1024 * 1024; // 分片阈值5MBasync function startUpload() {const file = document.getElementById('fileInput').files[0];if (!file) {layer.msg('请选择文件', {icon: 1});}// 根据文件大小选择上传方式if (file.size <= CHUNK_SIZE) {await directUpload(file);} else {await chunkedUpload(file);}}// 开始上传async function directUpload(file) {const formData = new FormData();formData.append('file', file);formData.append('file_name', file.name);// 显示进度条const progressBar = document.getElementById('progress');progressBar.innerHTML = '上传进度:0%';try {const res = await fetch('/api/directUpload', {method: 'POST',body: formData,});const data = await res.json();if (data.code === 1) {progressBar.innerHTML = '上传进度:100%';$("#c-name").val(data.name);$("#c-fullurl").val(data.fullurl);layer.msg('上传成功', {icon: 1});} else {throw new Error(data.msg);}} catch (error) {progressBar.innerHTML = '上传失败';console.error('直接上传失败:', error);}}async function chunkedUpload(file) {const totalChunks = Math.ceil(file.size / CHUNK_SIZE);let uploadedChunks = 0;// 初始化分片上传const initRes = await fetch('api/initUpload', {method: 'POST',body: JSON.stringify({filename: file.name}),headers: {'Content-Type': 'application/json'}});const initData = await initRes.json();if (initData.code !== 1) return alert('初始化失败');const {uploadId, objectName} = initData;const parts = [];// 上传所有分片for (let i = 0; i < totalChunks; i++) {const start = i * CHUNK_SIZE;const end = Math.min(start + CHUNK_SIZE, file.size);const chunk = file.slice(start, end);const formData = new FormData();formData.append('part', chunk);formData.append('uploadId', uploadId);formData.append('objectName', objectName);formData.append('partNumber', i + 1);const uploadRes = await fetch('api/uploadPart', {method: 'POST',body: formData});const partData = await uploadRes.json();if (partData.code === 1) {parts.push({PartNumber: partData.partNumber,ETag: partData.etag});uploadedChunks++;// 更新进度const progress = (uploadedChunks / totalChunks * 100).toFixed(2);document.getElementById('progress').innerHTML = `上传进度:${progress}%`;}}// 合并分片const completeRes = await fetch('api/completeUpload', {method: 'POST',body: JSON.stringify({uploadId,objectName,parts: JSON.stringify(parts)}),headers: {'Content-Type': 'application/json'}});const completeData = await completeRes.json();if (completeData.code === 1) {$("#c-name").val(completeData.name);$("#c-fullurl").val(completeData.fullurl);layer.msg('上传成功', {icon: 1});} else {layer.msg('上传失败' + completeData.msg, {icon: 2});}}
</script>

2. 后端控制器

<?phpnamespace app\****;use OSS\Core\OssException;
use OSS\OssClient;class Attachment
{// 初始化分片上传public function initUpload(){$object = 'uploads/' . date('Ymd') . '/' . $this->request->post('filename');try {$ossClient = new OssClient(config('alioss.accessKeyId'),config('alioss.accessKeySecret'),config('alioss.endpoint'));$uploadId = $ossClient->initiateMultipartUpload(config('alioss.bucket'), $object);return json(['code' => 1,'uploadId' => $uploadId,'objectName' => $object]);} catch (OssException $e) {return json(['code' => 0, 'msg' => $e->getMessage()]);}}// 上传分片public function uploadPart(){$data = $this->request->post();try {$ossClient = new OssClient(config('alioss.accessKeyId'),config('alioss.accessKeySecret'),config('alioss.endpoint'));$options = [OssClient::OSS_FILE_UPLOAD => $_FILES['part']['tmp_name'],OssClient::OSS_PART_NUM => $data['partNumber'],OssClient::OSS_CHECK_MD5 => true];$etag = $ossClient->uploadPart(config('alioss.bucket'),$data['objectName'],$data['uploadId'],$options);return json(['code' => 1,'etag' => $etag,'partNumber' => $data['partNumber']]);} catch (OssException $e) {return json(['code' => 0, 'msg' => $e->getMessage()]);}}// 完成上传public function completeUpload(){$data = $this->request->post();try {$ossClient = new OssClient(config('alioss.accessKeyId'),config('alioss.accessKeySecret'),config('alioss.endpoint'));$result = $ossClient->completeMultipartUpload(config('alioss.bucket'),$data['objectName'],$data['uploadId'],json_decode($data['parts'], true));return json(['code' => 1,'url' => $result['oss-request-url'],'name' => pathinfo($data['objectName'], PATHINFO_FILENAME),'fullurl' => strstr($result['oss-request-url'], '?', true),]);} catch (OssException $e) {return json(['code' => 0, 'msg' => $e->getMessage()]);}}// 直接上传完整文件public function directUpload(){try {$ossClient = new OssClient(config('alioss.accessKeyId'),config('alioss.accessKeySecret'),config('alioss.endpoint'));$file = $_FILES['file'];$file_name = $this->request->request('file_name', '');$object = 'uploads/' . date('Ymd') . '/' . $file['name'];$result = $ossClient->uploadFile(config('alioss.bucket'),$object,$file['tmp_name']);return json(['code' => 1,'url' => $result['oss-request-url'],'name' => pathinfo($file_name, PATHINFO_FILENAME),'fullurl' => $result['oss-request-url'],]);} catch (OssException $e) {return json(['code' => 0, 'msg' => $e->getMessage()]);}}
}
http://www.lryc.cn/news/2385224.html

相关文章:

  • 【场景分析】基于概率距离快速削减法的风光场景生成与削减方法
  • 【Java Web】3.SpringBootWeb请求响应
  • 单片机中断系统工作原理及定时器中断应用
  • LangGraph-agent-天气助手
  • 深度学习——超参数调优
  • 阿里云API RAG全流程实战:从模型调用到多模态应用的完整技术链路
  • 创建型:建造者模式
  • Jenkins集成Docker与K8S构建
  • redis缓存实战-19(使用 Pub/Sub 构建简单的聊天应用程序)
  • UE4游戏查找本地角色数据的方法-SDK
  • 游园安排--最长上升子序列+输出序列
  • 缓存一致性与AI内容生成的幂等控制
  • Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析
  • python web 开发-Flask-Login使用详解
  • 快速排序算法的C++和C语言对比
  • 分布式事务知识点整理
  • 微信小程序数据接收
  • 鸿蒙UI开发——badge角标的使用
  • 批量打印的趣事
  • 车载中央域控制器测试【BCM模块介绍-外灯3】
  • Linux系统基础——是什么、适用在哪里、如何选
  • MySQL与Oracle六大方面之比较
  • 二层和三层交换机的概念
  • 计算机网络学习20250524
  • 无损图片压缩 本地处理 批量处理提升效率 无需联网+无广告
  • C++标准库中 std::string 类提供的 insert 成员函数的不同重载版本
  • Qt window frame + windowTitle + windowIcon属性(3)
  • 解决:VMware 虚拟机 Ubuntu 系统共享文件夹无法访问问题
  • Dify源码学习
  • 静态网站部署:如何通过GitHub免费部署一个静态网站