国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

前端 + 后端 實(shí)現(xiàn)分片上傳(斷點(diǎn)續(xù)傳/極速秒傳)

這篇具有很好參考價(jià)值的文章主要介紹了前端 + 后端 實(shí)現(xiàn)分片上傳(斷點(diǎn)續(xù)傳/極速秒傳)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

先記錄下,后面有時(shí)間再去實(shí)現(xiàn)
(已實(shí)現(xiàn),可參考

  • SpringBoot+vue文件上傳&下載&預(yù)覽&大文件分片上傳&文件上傳進(jìn)度
  • SpringBoot+vue 大文件分片下載)

可參考鏈接:vue上傳大文件/視頻前后端(java)代碼

前端 + 后端 實(shí)現(xiàn)分片上傳(斷點(diǎn)續(xù)傳/極速秒傳)

前端slice分片上傳,后端用表記錄分片索引和分片大小和分片總數(shù),當(dāng)接受完最后一個(gè)分片(分片索引等于分片總數(shù),分片索引從1開始),就合并分片成完成的文件。前端需要遞歸上傳,并顯示加載動(dòng)畫和根據(jù)分片完成數(shù)量顯示進(jìn)度條

臨時(shí)demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="http://www.baidu.com/a">
        <input type="file" type="hidden" id="file"><!-- 隱藏這個(gè)原生的上傳文件按鈕 -->
        <button type="button" id="btn">觸發(fā)上傳</button></button><!-- 使用它來觸發(fā)選擇圖片動(dòng)作 -->
    </form>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<script>
    /* 監(jiān)聽選擇圖片的事件 */
    document.querySelector('#file').onchange =  (e)=>{
        console.log('改變了');
        console.log(this); // 這里的this變成了Window, 因?yàn)閷懗闪思^函數(shù)。
        console.dir(e.target); 

        // 選擇了一個(gè)文件,所以數(shù)組只有一個(gè)元素
        console.log(e.target.files); // FileList {0: File, length: 1}

        console.log(e.target.files[0]); // File {name: 'GIF 2023-4-1 18-14-01.gif', lastModified: 1680344051705, lastModifiedDate: Sat Apr 01 2023 18:14:11 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間), webkitRelativePath: '', size: 242914, …}

        upload(e.target.files[0])

        document.querySelector('#file').value = '' // 讓下次即使選擇同一個(gè)文件仍能觸發(fā)onchange事件
    }

    function upload(file) {
        console.log(file instanceof Blob); // true, 而Blob中有個(gè)slice方法,可以對(duì)文件進(jìn)行分片
        let formData = new FormData()

        let shardSize = 10 * 1024 * 1024
        let shardIndex = 1
        let start = shardSize * shardIndex
        let end = Math.min(file.size, start + shardSize)
        console.log(start,end);
        formData.append('mfile', file.slice(start,end))

        // 攜帶數(shù)據(jù)請(qǐng)求后臺(tái)
        $.ajax({
            url: 'http://127.0.0.1:8083/article/uploadImg',
            type: 'POST',
            data: formData,
            contentType: false,
            processData: false,
            cache: false,
            success: function (data) {
                if (data.success) {
                    alert('添加成功');
                } else {
                    alert('添加失敗');
                }
            }
        });
    }

    /* 點(diǎn)的是#btn,但是我們要觸發(fā)#file文件上傳 */
    document.querySelector('#btn').onclick = function(){
        document.querySelector('#file').click()
    }
</script>
</html>
@PostMapping("uploadImg")
public Result uploadImg(@RequestParam("mfile") MultipartFile mfile) throws IOException {
    String filename = mfile.getOriginalFilename();
    mfile.transferTo(new File("D:\\Projects\\vue-springboot\\src\\main\\resources\\static\\img\\"+filename));
    return Result.ok(filename);
}
spring:
  servlet:
    multipart:
      max-file-size: 50MB
      max-request-size: 50MB

oss 將前面的分片上傳改為oss里的追加上傳

public static void main(String[] args) throws IOException {
        
        // Endpoint以華東1(杭州)為例,其它Region請(qǐng)按實(shí)際情況填寫。
        String endpoint = "https://oss-cn-shenzhen.aliyuncs.com";
        // 阿里云賬號(hào)AccessKey擁有所有API的訪問權(quán)限,風(fēng)險(xiǎn)很高。強(qiáng)烈建議您創(chuàng)建并使用RAM用戶進(jìn)行API訪問或日常運(yùn)維,請(qǐng)登錄RAM控制臺(tái)創(chuàng)建RAM用戶。
        String accessKeyId = "xxx";
        String accessKeySecret = "yyy";
        // 填寫B(tài)ucket名稱,例如examplebucket。
        String bucketName = "test-zzhua";

        String objectName = "video/juc.mp4";

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        ObjectMetadata meta = new ObjectMetadata();
        meta.setObjectAcl(CannedAccessControlList.PublicRead);


        RandomAccessFile raFile = new RandomAccessFile(new File("D:\\Projects\\vue-springboot\\src\\main\\resources\\static\\img\\juc.mp4"), "r");

        long totalLen = raFile.length();

        // 定義每次追加上傳的大小 3M
        long everyLen = 3 * 1024 * 1024;

        long accLen = 0;


        byte[] bytes = new byte[5 * 1024]; // 緩沖數(shù)組5k

        while (true) {

            // 找到上次讀取的位置
            raFile.seek(accLen);

            boolean finish = false;

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 當(dāng)前讀取累積3M, 或不夠3M就讀完了
            int currLen = 0;

            while (true) {
                int readLen = raFile.read(bytes);
                if (readLen == -1) {
                    finish = true;
                    break;
                }
                currLen += readLen;
                baos.write(bytes, 0, readLen);
                if (currLen >= everyLen) {
                    break;
                }
            }

            // 發(fā)起追加請(qǐng)求
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, objectName, bais,meta);
            appendObjectRequest.setPosition(accLen);
            ossClient.appendObject(appendObjectRequest);

            if (finish) {
                break;
            }

            accLen += currLen;

        }


    }

md5大文件計(jì)算

javascript實(shí)現(xiàn)

參考:SpringBoot大文件上傳–前端計(jì)算文件的MD5

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/spark-md5/3.0.2/spark-md5.js"></script>
</head>
<body>
    <form id="from" method="post" action="/upload" enctype="multipart/form-data">
        <table>
            <tr>
                <td>
                    <input id="md5" name="md5">
                    <input id="file" name="upload" type="file">
                    <input id="submit" type="submit" value="上傳">
                </td>
            </tr>
        </table>
    </form>

</body>
<script>
    //注意此方法引用了SparkMD5庫(kù) library:https://github.com/satazor/SparkMD5
    //監(jiān)聽文本框變化
    document.getElementById("file").addEventListener("change", function() {
        //聲明必要的變量
        chunks=0;
        currentChunk=0;
        var fileReader = new FileReader();//一個(gè)用來讀取文件的對(duì)象
        //文件分割方法(注意兼容性)
        blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice,
            file = document.getElementById("file").files[0],
            //文件每塊分割2M,計(jì)算分割詳情
            chunkSize = 2097152,
            chunks = Math.ceil(file.size / chunkSize),//文件分成了幾塊
            currentChunk = 0,//當(dāng)前處理的第幾塊
            
            spark = new SparkMD5();//創(chuàng)建md5對(duì)象(基于SparkMD5)

       //每塊文件讀取完畢之后的處理
        fileReader.onload = function(e) {
            console.log("讀取文件", currentChunk + 1, "/", chunks);
            //每塊交由sparkMD5進(jìn)行計(jì)算
            spark.appendBinary(e.target.result);
            currentChunk++;
            //如果文件處理完成計(jì)算MD5,如果還有分片繼續(xù)處理
            if (currentChunk < chunks) {
                loadNext();
            } else {
                md5=spark.end();//最終的MD5
                console.log("MD5:"+md5);
            }
        };

        //處理單片文件的上傳
        function loadNext() {
            var start = currentChunk * chunkSize,
                end = start + chunkSize >= file.size ? file.size : start + chunkSize;
            fileReader.readAsBinaryString(blobSlice.call(file, start, end));
            //blobSlice.call(file, start, end)每次執(zhí)行到blobSlice的時(shí)候就會(huì)跳轉(zhuǎn)到blobSlice定義的地方,可以理解為一個(gè)循環(huán)
        }
        loadNext();
    });
</script>

</html>

java實(shí)現(xiàn)

參考:詳解JAVA中獲取文件MD5值的四種方法
須引入commons-codec包文章來源地址http://www.zghlxwxcb.cn/news/detail-416585.html

String s = DigestUtils.md5Hex(new FileInputStream(new File("D:\\documents\\尚硅谷谷粒學(xué)院項(xiàng)目視頻教程\\6 - What If I Want to Move Faster.mp4")));
ystem.out.println(s);

vue上傳大文件/視頻前后端(java)代碼

<template>
  <div>
    <!-- 上傳組件 -->
    <el-upload action drag :auto-upload="false" :show-file-list="false" :on-change="handleChange">
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">將文件拖到此處,或<em>點(diǎn)擊上傳</em></div>
      <div class="el-upload__tip" slot="tip">大小不超過 200M 的視頻</div>
    </el-upload>

    <!-- 進(jìn)度顯示 -->
    <div class="progress-box">
      <span>上傳進(jìn)度:{{ percent.toFixed() }}%</span>
      <el-button type="primary" size="mini" @click="handleClickBtn">{{ upload | btnTextFilter}}</el-button>
    </div>

    
  </div>
</template>

<script>
  import { getUUID } from '@/utils'
  import axios from 'axios'
  export default {
    name: 'singleUpload',
    props: {
     value: String
    },
    filters: {
      btnTextFilter(val) {
        return val ? '暫停' : '繼續(xù)'
      }
    },
    data() {
      return {
        videoUrl: this.value,
        percent: 0,
        upload: true,
        percentCount: 0,
        suffix: '',
        fileName: '',
        preName: ''
      }
    },
    methods: {
      emitInput(val) {
        this.$emit('input', val)
      },

    async handleChange(file) {
      if (!file) return
      this.percent = 0
      this.percentCount = 0
      // 獲取文件并轉(zhuǎn)成 ArrayBuffer 對(duì)象
      const fileObj = file.raw
    
      let buffer
      try {
        buffer = await this.fileToBuffer(fileObj)
      } catch (e) {
        console.log(e)
      }
      // 將文件按固定大?。?M)進(jìn)行切片,注意此處同時(shí)聲明了多個(gè)常量
      const chunkSize = 2097152,
          chunkList = [], // 保存所有切片的數(shù)組
          chunkListLength = Math.ceil(fileObj.size / chunkSize), // 計(jì)算總共多個(gè)切片
          suffix = /\.([0-9A-z]+)$/.exec(fileObj.name)[1] // 文件后綴名

      this.preName = getUUID() //生成文件名前綴
      this.fileName = this.preName+'.'+suffix //文件名 
      

      // 生成切片,這里后端要求傳遞的參數(shù)為字節(jié)數(shù)據(jù)塊(chunk)和每個(gè)數(shù)據(jù)塊的文件名(fileName)
      let curChunk = 0 // 切片時(shí)的初始位置
      for (let i = 0; i < chunkListLength; i++) {
        const item = {
          chunk: fileObj.slice(curChunk, curChunk + chunkSize),
          fileName: `${this.preName}_${i}.${suffix}` // 文件名規(guī)則按照 filename_1.jpg 命名
        }
        curChunk += chunkSize
        chunkList.push(item)
      }
      this.chunkList = chunkList // sendRequest 要用到
      this.sendRequest()
    },
    // 發(fā)送請(qǐng)求
    sendRequest() {
      const requestList = [] // 請(qǐng)求集合
      this.chunkList.forEach((item, index) => {
        const fn = () => {
          const formData = new FormData()
          formData.append('chunk', item.chunk)
          formData.append('filename', item.fileName)
          return axios({
            url: 'http://localhost/api/chunk',
            method: 'post',
            headers: { 'Content-Type': 'multipart/form-data' },
            data: formData
          }).then(response => {
            if (response.data.errcode === 0) { // 成功
              if (this.percentCount === 0) { // 避免上傳成功后會(huì)刪除切片改變 chunkList 的長(zhǎng)度影響到 percentCount 的值
                this.percentCount = 100 / this.chunkList.length
              }
              if (this.percent >= 100) {
                this.percent = 100;
              }else {
                this.percent += this.percentCount // 改變進(jìn)度
              }
              if (this.percent >= 100) {
                this.percent = 100;
              }
              this.chunkList.splice(index, 1) // 一旦上傳成功就刪除這一個(gè) chunk,方便斷點(diǎn)續(xù)傳
            }else{
                this.$mseeage({
                  type: "error",
                  message: response.data.message
                })
                return 
            }
          })
        }
        requestList.push(fn)
      })

      let i = 0 // 記錄發(fā)送的請(qǐng)求個(gè)數(shù)
      // 文件切片全部發(fā)送完畢后,需要請(qǐng)求 '/merge' 接口,把文件名傳遞給服務(wù)器
      const complete = () => {
        axios({
          url: 'http://localhost/api/merge',
          method: 'get',
          params: {filename: this.fileName },
          timeout: 60000
        }).then(response => {
          if (response.data.errcode === 0) { // 請(qǐng)求發(fā)送成功
            // this.videoUrl = res.data.path
            console.log(response.data)
          }
        })
      }
      const send = async () => {
        if (!this.upload) return
        if (i >= requestList.length) {
          // 發(fā)送完畢
          complete()
          return
        }
        await requestList[i]()
        i++
        send()
      }
      send() // 發(fā)送請(qǐng)求
        this.emitInput(this.fileName)
      },

      // 按下暫停按鈕
      handleClickBtn() {
        this.upload = !this.upload
        // 如果不暫停則繼續(xù)上傳
        if (this.upload) this.sendRequest()
      },

      // 將 File 對(duì)象轉(zhuǎn)為 ArrayBuffer 
      fileToBuffer(file) {
        return new Promise((resolve, reject) => {
          const fr = new FileReader()
          fr.onload = e => {
            resolve(e.target.result)
          }
          fr.readAsArrayBuffer(file)
          fr.onerror = () => {
            reject(new Error('轉(zhuǎn)換文件格式發(fā)生錯(cuò)誤'))
          }
        })
      }
    }
  }
</script>

<style scoped "">
  .progress-box {
    box-sizing: border-box;
    width: 360px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 10px;
    padding: 8px 10px;
    background-color: #ecf5ff;
    font-size: 14px;
    border-radius: 4px;
  }
  
.videoShow{
  width: 100%;
  height:600px;
  padding: 10px 0 50px;
  position: relative;
}
#videoBox{
  object-fit:fill;
  border-radius: 8px;
  display: inline-block;
  vertical-align: baseline;
}
.video-img{
	position: absolute;
    top: 0;
    bottom: 0;
    width: 100%;
    z-index: 999;
    background-size:100%;
	cursor:pointer;
    
  }
.video-img img {
  display:block;
  width: 60px;
  height: 60px;
  position: relative;
  top:260px;
  left: 48%;
}
video:focus {
  outline: -webkit-focus-ring-color auto 0px;

}
</style>



/**
 * 獲取uuid
 */
 export function getUUID () {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
  })
}

String dirPath = "D:\\video\\train"
@PostMapping("/chunk")
public Result upLoadChunk(@RequestParam("chunk") MultipartFile chunk,
                          @RequestParam("filename") String fileName) {
    // 用于存儲(chǔ)文件分片的文件夾
    File folder = new File(dirPath);
    if (!folder.exists() && !folder.isDirectory())
        folder.mkdirs();
    // 文件分片的路徑
    String filePath = dirPath + fileName;
    try {
        File saveFile = new File(filePath);
        // 寫入文件中
        //FileOutputStream fileOutputStream = new FileOutputStream(saveFile);
        //fileOutputStream.write(chunk.getBytes());
        //fileOutputStream.close();
        chunk.transferTo(saveFile);
        return new Result();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return new Result();
}



@GetMapping("/merge")
public Result MergeChunk(@RequestParam("filename") String filename) {

    String preName = filename.substring(0,filename.lastIndexOf("."));
    // 文件分片所在的文件夾
    File chunkFileFolder = new File(dirPath);
    // 合并后的文件的路徑
    File mergeFile = new File(dirPath + filename);
    // 得到文件分片所在的文件夾下的所有文件
    File[] chunks = chunkFileFolder.listFiles();
    System.out.println(chunks.length);
    assert chunks != null;
    // 排序
    File[] files = Arrays.stream(chunks)
            .filter(file -> file.getName().startsWith(preName))
            .sorted(Comparator.comparing(o -> Integer.valueOf(o.getName().split("\\.")[0].split("_")[1])))
            .toArray(File[]::new);

    try {
        // 合并文件
        RandomAccessFile randomAccessFileWriter = new RandomAccessFile(mergeFile, "rw");
        byte[] bytes = new byte[1024];
        for (File chunk : files) {
            RandomAccessFile randomAccessFileReader = new RandomAccessFile(chunk, "r");
            int len;
            while ((len = randomAccessFileReader.read(bytes)) != -1) {
                randomAccessFileWriter.write(bytes, 0, len);
            }
            randomAccessFileReader.close();
            System.out.println(chunk.getName());
            chunk.delete(); // 刪除已經(jīng)合并的文件
        }
        randomAccessFileWriter.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return new Result();
}


到了這里,關(guān)于前端 + 后端 實(shí)現(xiàn)分片上傳(斷點(diǎn)續(xù)傳/極速秒傳)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • minio&前后端分離上傳視頻/上傳大文件——前后端分離斷點(diǎn)續(xù)傳&minio分片上傳實(shí)現(xiàn)

    minio&前后端分離上傳視頻/上傳大文件——前后端分離斷點(diǎn)續(xù)傳&minio分片上傳實(shí)現(xiàn)

    ????????分布式文件系統(tǒng)-minio: 第一章:分布式文件系統(tǒng)介紹與minio介紹與使用(附minio java client 使用) 第二章:minio前后端分離上傳視頻/上傳大文件——前后端分離斷點(diǎn)續(xù)傳minio分片上傳實(shí)現(xiàn) 斷點(diǎn)續(xù)傳指的是在下載或上傳時(shí),將下載或上傳任務(wù)(一個(gè)文件或一個(gè)壓縮包

    2024年02月03日
    瀏覽(44)
  • 【SpringBoot整合系列】SpringBoot 實(shí)現(xiàn)大文件分片上傳、斷點(diǎn)續(xù)傳及秒傳

    【SpringBoot整合系列】SpringBoot 實(shí)現(xiàn)大文件分片上傳、斷點(diǎn)續(xù)傳及秒傳

    小文件(圖片、文檔、視頻)上傳可以直接使用很多ui框架封裝的上傳組件,或者自己寫一個(gè)input 上傳,利用FormData 對(duì)象提交文件數(shù)據(jù),后端使用spring提供的MultipartFile進(jìn)行文件的接收,然后寫入即可。 但是對(duì)于比較大的文件,比如上傳2G左右的文件(http上傳),就需要將文件

    2024年04月16日
    瀏覽(37)
  • springboot 、html分片上傳,斷點(diǎn)續(xù)傳

    后端代碼 注意:合并分片代碼中: Files.write(mergedFilePath, Files.readAllBytes(chunkFilePath), StandardOpenOption.APPEND); 如果不設(shè)置該值 StandardOpenOption.APPEND ,無法打開合并后的文件 前端代碼

    2024年02月05日
    瀏覽(21)
  • 【萬字長(zhǎng)文】Vue+SpringBoot實(shí)現(xiàn)大文件秒傳、斷點(diǎn)續(xù)傳和分片上傳完整教程(提供Gitee源碼)

    前言:最近在實(shí)際項(xiàng)目中碰到一個(gè)需求,客戶可能會(huì)上傳比較大的文件,如果采用傳統(tǒng)的文件上傳方案可能會(huì)存在服務(wù)器壓力大、資源浪費(fèi)甚至內(nèi)存溢出的一些安全風(fēng)險(xiǎn),所以為了解決一系列問題,需要采用新的技術(shù)方案來實(shí)現(xiàn)大文件的上傳;空閑的時(shí)候參考了網(wǎng)上的一些相

    2024年02月12日
    瀏覽(24)
  • spring boot 阿里云oss 文件分片上傳、斷點(diǎn)續(xù)傳

    spring boot 阿里云oss 文件分片上傳、斷點(diǎn)續(xù)傳

    文章目錄 前言 一、申請(qǐng)阿里云oss 二、上代碼 總結(jié) ? ? ? 阿里云對(duì)象存儲(chǔ)OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存儲(chǔ)服務(wù),可提供99.9999999999%(12個(gè)9)的數(shù)據(jù)持久性,99.995%的數(shù)據(jù)可用性。多種存儲(chǔ)類型供選擇,全面優(yōu)化存儲(chǔ)成本。 ? ? 您可以使用阿

    2024年02月07日
    瀏覽(27)
  • 大文件上傳阿里云oss,分片、斷點(diǎn)續(xù)傳進(jìn)度條展示

    大文件上傳阿里云oss,分片、斷點(diǎn)續(xù)傳進(jìn)度條展示

    前端頁(yè)面展示 大文件如果不采用分片上傳會(huì)導(dǎo)致卡死、內(nèi)存占用過高導(dǎo)致程序奔潰等一些列問題。 通常在文件大于100 MB的情況下,建議采用分片上傳的方法,通過斷點(diǎn)續(xù)傳和重試,提高上傳成功率。如果在文件小于100 MB的情況下使用分片上傳,且partSize設(shè)置不合理的情況下,

    2024年02月11日
    瀏覽(26)
  • springboot整合vue2-uploader文件分片上傳、秒傳、斷點(diǎn)續(xù)傳

    springboot整合vue2-uploader文件分片上傳、秒傳、斷點(diǎn)續(xù)傳

    vue-simple-uploader 是基于 simple-uploader.js 封裝的vue上傳插件。它的優(yōu)點(diǎn)包括且不限于以下幾種: 支持文件、多文件、文件夾上傳;支持拖拽文件、文件夾上傳 可暫停、繼續(xù)上傳 錯(cuò)誤處理 支持“秒傳”,通過文件判斷服務(wù)端是否已存在從而實(shí)現(xiàn)“秒傳” 分片上傳 支持進(jìn)度、預(yù)估

    2024年02月06日
    瀏覽(35)
  • 基于vue-simple-uploader封裝文件分片上傳、秒傳及斷點(diǎn)續(xù)傳的全局上傳

    基于vue-simple-uploader封裝文件分片上傳、秒傳及斷點(diǎn)續(xù)傳的全局上傳

    1. 前言 文件上傳 小文件(圖片、文檔、視頻)上傳可以直接使用很多ui框架封裝的上傳組件,或者自己寫一個(gè)input 上傳,利用FormData 對(duì)象提交文件數(shù)據(jù),后端使用spring提供的MultipartFile進(jìn)行文件的接收,然后寫入即可。但是對(duì)于比較大的文件,比如上傳2G左右的文件(http上傳

    2024年02月06日
    瀏覽(22)
  • aliyun-oss-sdk阿里云OSS視頻上傳(斷點(diǎn)續(xù)傳)前端實(shí)現(xiàn)

    aliyun-oss-sdk阿里云OSS視頻上傳(斷點(diǎn)續(xù)傳)前端實(shí)現(xiàn)

    最近上傳視頻的功能,突然炸了,兩年沒動(dòng)的代碼,突然不行遼,首次上傳成功,后面繼續(xù)上傳就可以,但凡有一次上傳失敗,再上傳文件就不行。 這里博主使用的是憑證上傳方式哈。 官方文檔:Web(JavaScript)上傳SDK 查看了官方文檔,確實(shí)是提到了,如使用1.5.3之前版本重

    2024年02月07日
    瀏覽(25)
  • 【前端面試】中大文件上傳/下載:中等文件代理服務(wù)器放行+大文件切片傳輸+并發(fā)請(qǐng)求+localstorage實(shí)現(xiàn)斷點(diǎn)續(xù)傳

    【前端面試】中大文件上傳/下載:中等文件代理服務(wù)器放行+大文件切片傳輸+并發(fā)請(qǐng)求+localstorage實(shí)現(xiàn)斷點(diǎn)續(xù)傳

    目錄 切片上傳~spark-md5 原理:流式計(jì)算+分塊處理 文件標(biāo)識(shí)spark-md5:A-B A.切片哈希值合并 B.首尾切片+其他切片前中后各取2M 計(jì)算hash:A-B(參考React的Fiber架構(gòu)) A.線程:web-worker B.空閑:requestIdleCallback 異步并發(fā)控制:A-B(參考http2的多路復(fù)用) A.promise.allSettled() B.并發(fā)數(shù)max=

    2024年02月12日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包