Vue Bootstrap OSS 实现文件追加上传、断点续传、极速秒传
生活随笔
收集整理的這篇文章主要介紹了
Vue Bootstrap OSS 实现文件追加上传、断点续传、极速秒传
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
公司實現文件上傳技術選型采用后端SpringBoot/Cloud,前端vue Bootstrap ,阿里云OSS作為文件存儲,大文件上傳功能單獨抽取封裝大文件上傳組件,可供所有的大文件的操作。
| SpringBoot | 2.5.6 |
| Spring-Cloud | 2020.0.4 |
| mysql | 8.0.26 |
| pagehelper | 1.3.1 |
| Mybatis | 2.2.0 |
| Redis | 5.0 |
| Fastjson | 1.2.78 |
| Vue | 2.6.11 |
| axios | 0.24.0 |
| vue-router | 3.5.3 |
| Bootstrap | 4.6.2 |
文章目錄
- 一、前端部分
- 1. 小節頁面
- 2. js部分
- 3. 大文件上傳組件
- 二、阿里云OSS
- 2.1. 注冊阿里云
- 2.2. 開通OSS
- 2.3. 進入管控臺
- 2.4. 創建 Bucket
- 2.5. 創建OSS用戶
- 2.6. OSS權限
- 三、OSS Client 開發文檔
- 3.1. OSS Client SDK
- 3.2. 限制
- 3.3. SDK Client
- 四、后端部分
- 4.1.依賴引入
- 4.2. 配置
- 4.3. api接口
一、前端部分
1. 小節頁面
小節頁面作為文件上傳父頁面
2. js部分
<script>import BigFile from "@/components/big-file";export default {components: { BigFile },name: 'business-section',data: function () {return {section: {},sections: [],FILE_USE: FILE_USE,}},methods: {/*** 點擊【新增】*/add() {let _this = this_this.section = {}$("#form-modal").modal("show")},/*** 點擊【編輯】*/edit(section) {let _this = this_this.section = $.extend({}, section)$("#form-modal").modal("show")},/*** 點擊【保存】*/save() {let _this = this_this.section.video = "";// 保存校驗if (1 != 1|| !Validator.require(_this.section.title, "標題")|| !Validator.length(_this.section.title, "標題", 1, 50)|| !Validator.length(_this.section.video, "視頻", 1, 200)) {return;}_this.section.courseId = _this.course.id_this.section.chapterId = _this.chapter.idLoading.show()_this.$api.post(process.env.VUE_APP_SERVER + '/business/admin/section/save', _this.section).then((res) => {Loading.hide()let resp = res.dataif (resp.success) {$("#form-modal").modal("hide")_this.list(1)Toast.success("保存成功!")} else {Toast.warning(resp.message)}})},afterUpload(resp) {let _this = thislet video = resp.content.path;},}, }</script>3. 大文件上傳組件
<template><div><button type="button" v-on:click="selectFile()" class="btn btn-white btn-default btn-round"><i class="ace-icon fa fa-upload"></i>{{ text }}</button><input class="hidden" type="file" ref="file" v-on:change="uploadFile()" v-bind:id="inputId+'-input'"></div> </template><script> export default {name: 'big-file',props: {text: {default: "上傳大文件"},inputId: {default: "file-upload"},suffixs: {default: []},use: {default: ""},shardSize: {default: 50 * 1024},url: {default: "oss-append"},saveType: {default: "oss/"},afterUpload: {type: Function,default: null},},data: function () {return {}},methods: {uploadFile() {let _this = this;let formData = new window.FormData();let file = _this.$refs.file.files[0];console.log(JSON.stringify(file));/*name: "test.mp4"lastModified: 1901173357457lastModifiedDate: Tue May 27 2099 14:49:17 GMT+0800 (中國標準時間) {}webkitRelativePath: ""size: 37415970type: "video/mp4"*/// 生成文件標識,標識多次上傳的是不是同一個文件let key = hex_md5(file.name + file.size + file.type);let key10 = parseInt(key, 16);let key62 = Tool._10to62(key10);console.log(key, key10, key62);console.log(hex_md5(Array()));/*d41d8cd98f00b204e9800998ecf8427e2.8194976848941264e+386sfSqfOwzmik4A4icMYuUe*/// 判斷文件格式let suffixs = _this.suffixs;let fileName = file.name;let suffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowerCase();let validateSuffix = false;for (let i = 0; i < suffixs.length; i++) {if (suffixs[i].toLowerCase() === suffix) {validateSuffix = true;break;}}if (!validateSuffix) {Toast.warning("文件格式不正確!只支持上傳:" + suffixs.join(","));$("#" + _this.inputId + "-input").val("");return;}// 文件分片// let shardSize = 10 * 1024 * 1024; //以10MB為一個分片// let shardSize = 50 * 1024; //以50KB為一個分片let shardSize = _this.shardSize;let shardIndex = 1; //分片索引,1表示第1個分片let size = file.size;let shardTotal = Math.ceil(size / shardSize); //總片數let param = {'shardIndex': shardIndex,'shardSize': shardSize,'shardTotal': shardTotal,'use': _this.use,'name': file.name,'suffix': suffix,'size': file.size,'key': key62};_this.check(param);},/*** 檢查文件狀態,是否已上傳過?傳到第幾個分片?*/check(param) {let _this = this;_this.$api.get(process.env.VUE_APP_SERVER + '/file/admin/check/' + _this.saveType + param.key).then((response) => {let resp = response.data;if (resp.success) {let obj = resp.content;if (!obj) {param.shardIndex = 1;console.log("沒有找到文件記錄,從分片1開始上傳");_this.upload(param);} else if (obj.shardIndex === obj.shardTotal) {// 已上傳分片 = 分片總數,說明已全部上傳完,不需要再上傳Toast.success("文件極速秒傳成功!");_this.afterUpload(resp);$("#" + _this.inputId + "-input").val("");} else {param.shardIndex = obj.shardIndex + 1;console.log("找到文件記錄,從分片" + param.shardIndex + "開始上傳");_this.upload(param);}} else {Toast.warning("文件上傳失敗");$("#" + _this.inputId + "-input").val("");}})},/*** 將分片數據轉成base64進行上傳*/upload(param) {let _this = this;let shardIndex = param.shardIndex;let shardTotal = param.shardTotal;let shardSize = param.shardSize;let fileShard = _this.getFileShard(shardIndex, shardSize);// 將圖片轉為base64進行傳輸let fileReader = new FileReader();Progress.show(parseInt((shardIndex - 1) * 100 / shardTotal));fileReader.onload = function (e) {let base64 = e.target.result;// console.log("base64:", base64);param.shard = base64;_this.$api.post(process.env.VUE_APP_SERVER + '/file/admin/' + _this.url, param).then((response) => {let resp = response.data;console.log("上傳文件成功:", resp);Progress.show(parseInt(shardIndex * 100 / shardTotal));if (shardIndex < shardTotal) {// 上傳下一個分片param.shardIndex = param.shardIndex + 1;_this.upload(param);} else {Progress.hide();_this.afterUpload(resp);$("#" + _this.inputId + "-input").val("");}});};fileReader.readAsDataURL(fileShard);},getFileShard(shardIndex, shardSize) {let _this = this;let file = _this.$refs.file.files[0];let start = (shardIndex - 1) * shardSize; //當前分片起始位置let end = Math.min(file.size, start + shardSize); //當前分片結束位置let fileShard = file.slice(start, end); //從文件中截取當前的分片數據return fileShard;},selectFile() {let _this = this;$("#" + _this.inputId + "-input").trigger("click");}} } </script>二、阿里云OSS
官網:https://www.aliyun.com
2.1. 注冊阿里云
https://account.aliyun.com/register/register.htm
2.2. 開通OSS
2.3. 進入管控臺
2.4. 創建 Bucket
讀寫權限選擇【公共讀】,意思是都可以或者有權限看,沒其他特殊請求,其他的保持默認,點擊確定即可
2.5. 創建OSS用戶
或者
2.6. OSS權限
三、OSS Client 開發文檔
https://www.aliyun.com/product/oss
3.1. OSS Client SDK
開發語言java 追加上傳(斷點續傳已實現)
3.2. 限制
3.3. SDK Client
這里就是官網提供的java語言的SDK Client
四、后端部分
https://help.aliyun.com/document_detail/32009.html
4.1.依賴引入
<!-- OSS Java SDK --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version></dependency>4.2. 配置
# 應用名稱 spring.application.name=file # 應用端口 server.port=9003 # 注冊到eureka eureka.client.service-url.defaultZone=http://localhost:8761/eureka# 請求訪問前綴 server.servlet.context-path=/file# 本地存儲靜態文件路徑 file.path=D:/file/imooc/course/ # 訪問靜態文件路徑(用于文件回顯或者文件下載) file.domain=http://127.0.0.1:9000/file/f/# 文件大小(如果搭建大小超過此配置的大小或拋出異常) spring.servlet.multipart.max-file-size=50MB # 請求大小 spring.servlet.multipart.max-request-size=50MB# OSS 配置 oss.accessKeyId=xxx oss.accessKeySecret=xxx oss.endpoint=http://oss-cn-beijing.aliyuncs.com oss.ossDomain=http://bucket名稱.oss-cn-beijing.aliyuncs.com/ oss.bucket=xxx-
oss.endpoint 和oss.ossDomain獲取方式
-
bucket 獲取方式
-
oss.accessKeyId和oss.accessKeySecret獲取方式
4.3. api接口
package com.course.file.controller.admin;import com.alibaba.fastjson.JSON; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.model.AppendObjectRequest; import com.aliyun.oss.model.AppendObjectResult; import com.aliyun.oss.model.ObjectMetadata; import com.aliyun.oss.model.PutObjectRequest; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.vod.model.v20170321.GetMezzanineInfoResponse; import com.course.server.dto.FileDto; import com.course.server.dto.ResponseDto; import com.course.server.enums.FileUseEnum; import com.course.server.service.FileService; import com.course.server.util.Base64ToMultipartFile; import com.course.server.util.UuidUtil; import com.course.server.util.VodUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource; import java.io.ByteArrayInputStream;@RequestMapping("/admin") @RestController public class OssController {public static final Logger LOG = LoggerFactory.getLogger(OssController.class);public static final String BUSINESS_NAME = "文件上傳";@Value("${oss.accessKeyId}")private String accessKeyId;@Value("${oss.accessKeySecret}")private String accessKeySecret;@Value("${oss.endpoint}")private String endpoint;@Value("${oss.bucket}")private String bucket;@Value("${oss.ossDomain}")private String ossDomain;@Resourceprivate FileService fileService;/*** oss追加上傳** @param fileDto* @return* @throws Exception*/@PostMapping("/oss-append")public ResponseDto fileUpload(@RequestBody FileDto fileDto) throws Exception {LOG.info("上傳文件開始");//接收前端的歸屬文件類型 COURSE("C", "課程"), TEACHER("T", "講師");String use = fileDto.getUse();// 為了支持一個文件上傳多次,展示歷史的不同版本,因此上傳文件前,統一添加文件前綴,下載時,統一截取文件沒那個前8位處理String key = fileDto.getKey();//分片索引,1表示第1個分片Integer shardIndex = fileDto.getShardIndex();// 文件分片大小 shardSize = 10 * 1024 * 1024;// 以10MB為一個分片Integer shardSize = fileDto.getShardSize();// 具體的文件 由于為了統一使用FileDto對象接收,默認接收類型是MultipartFile,這里現在接收類型是String ,前端將文件提前轉成了Base64String shardBase64 = fileDto.getShard();// 將具體的文件在由Base64轉成MultipartFile類型MultipartFile shard = Base64ToMultipartFile.base64ToMultipart(shardBase64);//接收前端的歸屬文件類型 COURSE("C", "課程"), TEACHER("T", "講師");FileUseEnum useEnum = FileUseEnum.getByCode(use);//文件全名String filename = shard.getOriginalFilename();//如果文件夾不存在,則創建String dir = useEnum.name().toLowerCase();String path = new StringBuffer(dir).append("/").append(key).append(".").append(filename).toString();// course\6sfSqfOwzmik4A4icMYuUe.mp4// 創建OSSClient實例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);ObjectMetadata meta = new ObjectMetadata();// 指定上傳的內容類型。meta.setContentType("text/plain");// 通過AppendObjectRequest設置多個參數。AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucket, path,new ByteArrayInputStream(shard.getBytes()), meta);// 通過AppendObjectRequest設置單個參數。// 設置Bucket名稱。//appendObjectRequest.setBucketName(bucketName);// 設置Object名稱。即不包含Bucket名稱在內的Object的完整路徑,例如example/test.txt。//appendObjectRequest.setKey(objectName);// 設置待追加的內容。可選類型包括InputStream類型和File類型。此處為InputStream類型。//appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));// 設置待追加的內容。可選類型包括InputStream類型和File類型。此處為File類型。//appendObjectRequest.setFile(new File("D:\\localpath\\examplefile.txt"));// 指定文件的元信息,第一次追加時有效。//appendObjectRequest.setMetadata(meta);// 第一次追加。// 設置文件的追加位置。// appendObjectRequest.setPosition(0L);appendObjectRequest.setPosition((long) (shardIndex - 1) * shardSize);AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);// 文件的64位CRC值。此值根據ECMA-182標準計算得出System.out.println(appendObjectResult.getObjectCRC());// 關閉OSSClient。ossClient.shutdown();LOG.info("保存文件記錄開始");fileDto.setPath(path);fileService.save(fileDto);ResponseDto responseDto = new ResponseDto();// 文件OSS地址存儲到fileDto,統一返回前端fileDto.setPath(ossDomain + path);responseDto.setContent(fileDto);return responseDto;}/*** 斷點續傳檢查** @param key* @return* @throws Exception*/@GetMapping("/check/oss/{key}")public ResponseDto check(@PathVariable String key) throws Exception {LOG.info("檢查上傳分片開始:{}", key);ResponseDto responseDto = new ResponseDto();FileDto fileDto = fileService.findByKey(key);if (fileDto != null) {fileDto.setPath(ossDomain + fileDto.getPath());}responseDto.setContent(fileDto);return responseDto;} } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Vue Bootstrap OSS 实现文件追加上传、断点续传、极速秒传的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot spring-cl
- 下一篇: RuoYi-Cloud 部署篇_01(w