亚洲精品亚洲人成在线观看麻豆,在线欧美视频一区,亚洲国产精品一区二区动图,色综合久久丁香婷婷

              當前位置:首頁 > IT技術 > Web編程 > 正文

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳
              2022-09-06 22:35:06


              公司實現(xiàn)文件上傳技術選型采用后端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. 小節(jié)頁面

              小節(jié)頁面作為文件上傳父頁面

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_java

              <div class="form-group">
              <label class="col-sm-2 control-label">視頻</label>
              <div class="col-sm-10">
              <vod :text="'上傳視頻'"
              :input-id="'video-upload'"
              :suffixs="['mp4']"
              :use="FILE_USE.COURSE.key"
              :after-upload="afterUpload">
              </vod>

              <div v-show="section.video" class="row">
              <div class="col-md-9">
              <player v-bind:player-id="'form-player-div'"
              ref="player"></player>
              <video v-bind:src="section.video" id="video" controls="controls" class="hidden"></video>
              </div>
              </div>
              </div>
              </div>
              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.id

              Loading.show()
              _this.$api.post(process.env.VUE_APP_SERVER + '/business/admin/section/save', _this.section).then((res) => {
              Loading.hide()
              let resp = res.data
              if (resp.success) {
              $("#form-modal").modal("hide")
              _this.list(1)
              Toast.success("保存成功!")
              } else {
              Toast.warning(resp.message)
              }
              })
              },

              afterUpload(resp) {
              let _this = this
              let 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: 1901173357457
              lastModifiedDate: Tue May 27 2099 14:49:17 GMT+0800 (中國標準時間) {}
              webkitRelativePath: ""
              size: 37415970
              type: "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()));
              /*
              d41d8cd98f00b204e9800998ecf8427e
              2.8194976848941264e+38
              6sfSqfOwzmik4A4icMYuUe
              */

              // 判斷文件格式
              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); //總片數(shù)

              let param = {
              'shardIndex': shardIndex,
              'shardSize': shardSize,
              'shardTotal': shardTotal,
              'use': _this.use,
              'name': file.name,
              'suffix': suffix,
              'size': file.size,
              'key': key62
              };

              _this.check(param);
              },


              /**
              * 檢查文件狀態(tài),是否已上傳過?傳到第幾個分片?
              */
              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) {
              // 已上傳分片 = 分片總數(shù),說明已全部上傳完,不需要再上傳
              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("");
              }
              })
              },

              /**
              * 將分片數(shù)據(jù)轉成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); //從文件中截取當前的分片數(shù)據(jù)
              return fileShard;
              },

              selectFile() {
              let _this = this;
              $("#" + _this.inputId + "-input").trigger("click");
              }
              }
              }
              </script>
              二、阿里云OSS

              官網(wǎng):??https://www.aliyun.com??

              2.1. 注冊阿里云

              ??https://account.aliyun.com/register/register.htm??

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_vue.js_02

              2.2. 開通OSS

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_vue.js_03


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_java_04

              2.3. 進入管控臺

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_java_05


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_ide_06

              2.4. 創(chuàng)建 Bucket

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_上傳_07

              讀寫權限選擇【公共讀】,意思是都可以或者有權限看,沒其他特殊請求,其他的保持默認,點擊確定即可

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_上傳_08


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_vue.js_09

              2.5. 創(chuàng)建OSS用戶

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_ide_10


              或者

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_上傳_11


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_ide_12


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_java_13

              2.6. OSS權限

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_vue.js_14


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_java_15

              三、OSS Client 開發(fā)文檔

              ??https://www.aliyun.com/product/oss??

              3.1. OSS Client SDK

              開發(fā)語言java 追加上傳(斷點續(xù)傳已實現(xiàn))

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_ide_16


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_上傳_17

              3.2. 限制

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_bootstrap_18

              3.3. SDK Client

              這里就是官網(wǎng)提供的java語言的SDK Client

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_java_19

              四、后端部分

              ??https://help.aliyun.com/document_detail/32009.html??

              4.1.依賴引入

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_java_20

              <!-- 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

              # 本地存儲靜態(tài)文件路徑
              file.path=D:/file/imooc/course/
              # 訪問靜態(tài)文件路徑(用于文件回顯或者文件下載)
              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獲取方式
              • Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_ide_21

              • bucket 獲取方式
              • Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_上傳_22

              • oss.accessKeyId和oss.accessKeySecret獲取方式

              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_vue.js_23


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_java_24


              Vue Bootstrap OSS 實現(xiàn)文件追加上傳、斷點續(xù)傳、極速秒傳_上傳_25

              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;

              @Resource
              private 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();
              // 為了支持一個文件上傳多次,展示歷史的不同版本,因此上傳文件前,統(tǒng)一添加文件前綴,下載時,統(tǒng)一截取文件沒那個前8位處理
              String key = fileDto.getKey();
              //分片索引,1表示第1個分片
              Integer shardIndex = fileDto.getShardIndex();
              // 文件分片大小 shardSize = 10 * 1024 * 1024;
              // 以10MB為一個分片
              Integer shardSize = fileDto.getShardSize();
              // 具體的文件 由于為了統(tǒng)一使用FileDto對象接收,默認接收類型是MultipartFile,這里現(xiàn)在接收類型是String ,前端將文件提前轉成了Base64
              String shardBase64 = fileDto.getShard();
              // 將具體的文件在由Base64轉成MultipartFile類型
              MultipartFile shard = Base64ToMultipartFile.base64ToMultipart(shardBase64);

              //接收前端的歸屬文件類型 COURSE("C", "課程"), TEACHER("T", "講師");
              FileUseEnum useEnum = FileUseEnum.getByCode(use);

              //文件全名
              String filename = shard.getOriginalFilename();
              //如果文件夾不存在,則創(chuàng)建
              String dir = useEnum.name().toLowerCase();
              String path = new StringBuffer(dir)
              .append("/")
              .append(key)
              .append(".")
              .append(filename)
              .toString();// course6sfSqfOwzmik4A4icMYuUe.mp4

              // 創(chuàng)建OSSClient實例。
              OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

              ObjectMetadata meta = new ObjectMetadata();
              // 指定上傳的內(nèi)容類型。
              meta.setContentType("text/plain");

              // 通過AppendObjectRequest設置多個參數(shù)。
              AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucket, path,
              new ByteArrayInputStream(shard.getBytes()), meta);

              // 通過AppendObjectRequest設置單個參數(shù)。
              // 設置Bucket名稱。
              //appendObjectRequest.setBucketName(bucketName);
              // 設置Object名稱。即不包含Bucket名稱在內(nèi)的Object的完整路徑,例如example/test.txt。
              //appendObjectRequest.setKey(objectName);
              // 設置待追加的內(nèi)容??蛇x類型包括InputStream類型和File類型。此處為InputStream類型。
              //appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));
              // 設置待追加的內(nèi)容??蛇x類型包括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值。此值根據(jù)ECMA-182標準計算得出
              System.out.println(appendObjectResult.getObjectCRC());

              // 關閉OSSClient。
              ossClient.shutdown();

              LOG.info("保存文件記錄開始");
              fileDto.setPath(path);
              fileService.save(fileDto);

              ResponseDto responseDto = new ResponseDto();
              // 文件OSS地址存儲到fileDto,統(tǒng)一返回前端
              fileDto.setPath(ossDomain + path);
              responseDto.setContent(fileDto);

              return responseDto;
              }

              /**
              * 斷點續(xù)傳檢查
              *
              * @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;
              }
              }


              本文摘自 :https://blog.51cto.com/g

              開通會員,享受整站包年服務立即開通 >