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

使用MinIO文件存儲系統(tǒng)【完成視頻斷點(diǎn)續(xù)傳】業(yè)務(wù)邏輯

這篇具有很好參考價(jià)值的文章主要介紹了使用MinIO文件存儲系統(tǒng)【完成視頻斷點(diǎn)續(xù)傳】業(yè)務(wù)邏輯。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

目錄

視頻上傳

接口一:檢查該視頻/媒資文件是否已經(jīng)上傳完成

接口二:檢查視頻分塊是否已經(jīng)在minio中已經(jīng)存在

接口三:上傳分塊文件到minio中(已經(jīng)上傳的分塊會在接口二進(jìn)行校驗(yàn))

接口四:合并上傳的分塊文件保存文件合并后的文件信息


視頻上傳

視頻上傳流程圖

minio 視頻文件,在線教育項(xiàng)目,java,javascript,minio

接口一:檢查該視頻/媒資文件是否已經(jīng)上傳完成

首先:前端計(jì)算上傳視頻的MD5傳遞給后端,后端接收到MD5值之后,通過MD5到媒資管理表中查詢是否存在該文件信息,如果存在并且從媒資管理表中獲取這個(gè)文件存放在minio的位置,通過位置到minio分布式文件系統(tǒng)中查詢文件是否存在,如果mysql媒資信息表和minio中的媒資文件都存在返回true,無需進(jìn)行后續(xù)上傳,如果不存在返回前端false用來。

controller層

    @ApiOperation(value = "文件上傳前檢查文件")
    @PostMapping("/upload/checkfile")
    public RestResponse<Boolean> checkfile(@RequestParam("fileMd5") String fileMd5) throws Exception {
        RestResponse<Boolean> booleanRestResponse = mediaFilesService.checkFile(fileMd5);
        return booleanRestResponse;
    }

?service層

接口:

    public RestResponse<Boolean> checkFile(String fileMd5);

實(shí)現(xiàn)類:

    /**
     * 通過md5值在數(shù)據(jù)庫判斷該文件是否存在
     * @param fileMd5 文件的md5
     * @return
     */
    @Override
    public RestResponse<Boolean> checkFile(String fileMd5) {
        MediaFiles mediaFiles = baseMapper.selectById(fileMd5);
        //說明在數(shù)據(jù)庫中已經(jīng)存在
        if (mediaFiles!=null){
            //檢查在minio中是否存在
            //桶
            String bucket = mediaFiles.getBucket();
            //存儲目錄
            String filePath = mediaFiles.getFilePath();
            //文件流
            InputStream stream = null;
            try {
                stream = minioClient.getObject(GetObjectArgs.builder().bucket(bucket).object(filePath).build());
                if (stream!=null){
                    //return 文件已經(jīng)存在
                    return RestResponse.success(true);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return RestResponse.success(false);
    }

接口二:檢查視頻分塊是否已經(jīng)在minio中已經(jīng)存在

首先接收前端上傳媒資文件所生成的md5和分塊序號,通過文件的md5值和文件每一塊的序號組成在minio中存儲分塊文件的位置,獲取該位置的分塊文件是否存在,如果存在返回true(說明該分塊文件已經(jīng)在此前完成過上傳,無需再次上傳),如果不存在返回false,說明該分塊文件還未上傳,重新上傳這一塊文件。

controller層(控制層)

    @ApiOperation(value = "分塊文件上傳前的檢測")
    @PostMapping("/upload/checkchunk")
    public RestResponse<Boolean> checkchunk(@RequestParam("fileMd5") String fileMd5, @RequestParam("chunk") int chunk) throws Exception {
        RestResponse<Boolean> booleanRestResponse = mediaFilesService.checkChunk(fileMd5,chunk);
        return booleanRestResponse;
    }

?service層(業(yè)務(wù)邏輯層)

接口:

    public RestResponse<Boolean> checkChunk(String fileMd5, int chunkIndex);

接口實(shí)現(xiàn)類:

 /**
     * 檢查分塊是否已經(jīng)存在
     * @param fileMd5  文件的md5
     * @param chunkIndex  分塊序號
     * @return
     */
    @Override
    public RestResponse<Boolean> checkChunk(String fileMd5, int chunkIndex) {
        //獲取所在的桶
        String bucket = BUCKET_VIDEO;
        //分塊文件的路徑
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5) + chunkIndex;

        //文件流
        InputStream inputStream = null;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucket).object(chunkFileFolderPath).build());
        } catch (Exception e) {
            e.printStackTrace();
            log.debug("分塊不存在");
        }
        if (inputStream !=null){
            return RestResponse.success(true);
        }
        return RestResponse.success(false);
    }

接口三:上傳分塊文件到minio中(已經(jīng)上傳的分塊會在接口二進(jìn)行校驗(yàn))

接收前端傳來的分割好的5M文件和這個(gè)文件的分割序號以及完整文件的md5值,將文件在本地轉(zhuǎn)儲一下,進(jìn)行上傳,如果是用戶原先上傳一半停止了上傳或者由于網(wǎng)絡(luò)波動(dòng)導(dǎo)致上傳中斷,下一次上傳原先文件時(shí)會在接口二中判斷原先文件的哪幾塊已經(jīng)存在minio中,存在的分塊無需再次上傳,不存在的分塊走上傳分塊文件接口進(jìn)行上傳分塊文件。

controller層(控制層)

    @ApiOperation(value = "上傳分塊文件")
    @PostMapping("/upload/uploadchunk")
    public RestResponse uploadchunk(@RequestParam("file") MultipartFile file, @RequestParam("fileMd5") String fileMd5, @RequestParam("chunk") int chunk) throws Exception {
        System.out.println(fileMd5);
        System.out.println("分塊文件序號:"+chunk);
        //創(chuàng)建臨時(shí)文件
        File tempFile = File.createTempFile("minio", "temp");
        //上傳的文件拷貝到臨時(shí)文件
        file.transferTo(tempFile);
        //文件路徑
        String absolutePath = tempFile.getAbsolutePath();

        RestResponse restResponse = mediaFilesService.uploadChunk(fileMd5, chunk, absolutePath);
        return restResponse;
    }

service(業(yè)務(wù)邏輯層)

接口:

    /**
     * @description 上傳分塊
     * @param fileMd5  文件md5
     * @param chunk  分塊序號
     * @param  localfChunkFilePath 本地文件路徑
     */
    public RestResponse uploadChunk(String fileMd5,int chunk,String localfChunkFilePath);

實(shí)現(xiàn)類:

@Override
    public RestResponse uploadChunk(String fileMd5, int chunk, String localfChunkFilePath) {
        //得到分塊文件的路徑
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5);
        //
        String chunkFilePath = chunkFileFolderPath + chunk;
        //得到文件類型
        String mimeType = getMimeType(null);
        //上傳分塊文件到minio
        boolean flag = false;
        try {
            flag = addMediaFilesToMinIO(localfChunkFilePath, mimeType, BUCKET_VIDEO, chunkFilePath);
        } catch (Exception e) {
            log.debug("上傳分塊文件:{},失敗:{}",chunkFilePath,e.getMessage());
        }
        if (!flag){
            return RestResponse.validfail(false,"上傳分塊文件失敗");
        }

        return RestResponse.success(true);
    }

上傳文件的方法

    /**
     * @description 將文件寫入minIO
     * @param localFilePath  文件地址
     * @param bucket  桶
     * @param objectName 對象名稱
     */
    public boolean addMediaFilesToMinIO(String localFilePath,String mimeType,String bucket, String objectName) {
        try {
            UploadObjectArgs testbucket = UploadObjectArgs.builder()
                    .bucket(bucket)
                    .object(objectName)
                    .filename(localFilePath)
                    .contentType(mimeType)
                    .build();
            minioClient.uploadObject(testbucket);
            log.info("上傳文件到minio成功,bucket:{},objectName:{}",bucket,objectName);
            System.out.println("上傳成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上傳文件到minio出錯(cuò),bucket:{},objectName:{},錯(cuò)誤原因:{}",bucket,objectName,e.getMessage(),e);
            XueChengPlusException.cast("上傳文件到文件系統(tǒng)失敗");
        }
        return false;
    }

接口四:合并上傳的分塊文件保存文件合并后的文件信息

當(dāng)前端按照5M將文件切分好依次上傳所有之后,會請求接口四(合并文件),后端接收原文件的md5值和上傳文件的名稱和分塊總數(shù),在業(yè)務(wù)層進(jìn)行處理,

1:首先會通過md5值獲取在minio中存儲該文件的分塊位置目錄

2:通過接收到分塊總數(shù)和存儲分塊的位置得到所有分塊文件的存儲的具體位置存放到集合中

3:通過位置路徑調(diào)用minio的合并api,將文件合并。

4:將合并好的文件臨時(shí)下載到本地獲得合并文件的md5值和前端上傳文件的md5進(jìn)行比較

5:刪除臨時(shí)本地的臨時(shí)文件,如果校驗(yàn)通過存儲該文件的相關(guān)信息到mysql媒資表中

6:就是將minio中存儲的分塊文件給刪除。

controller層

    @ApiOperation(value = "合并文件")
    @PostMapping("/upload/mergechunks")
    public RestResponse mergechunks(@RequestParam("fileMd5") String fileMd5, @RequestParam("fileName") String fileName, @RequestParam("chunkTotal") int chunkTotal) throws Exception {
        System.out.println(fileMd5);
        System.out.println(chunkTotal);
        Long companyId = 1232141425L;
        UploadFileParamsDto uploadFileParamsDto = new UploadFileParamsDto();
        uploadFileParamsDto.setFileType("001002");
        uploadFileParamsDto.setTags("課程視頻");
        uploadFileParamsDto.setRemark("");
        uploadFileParamsDto.setFilename(fileName);
        return mediaFilesService.mergechunks(companyId,fileMd5,chunkTotal,uploadFileParamsDto);
    }

業(yè)務(wù)層

接口

    /**
     * @description 合并分塊
     * @param companyId  機(jī)構(gòu)id
     * @param fileMd5  文件md5
     * @param chunkTotal 分塊總和
     * @param uploadFileParamsDto 文件信息
     */
    public RestResponse mergechunks(Long companyId,String fileMd5,int chunkTotal,UploadFileParamsDto uploadFileParamsDto);

實(shí)現(xiàn)類:

    @Override
    public RestResponse mergechunks(Long companyId, String fileMd5, int chunkTotal, UploadFileParamsDto uploadFileParamsDto) {
        //=====獲取分塊文件路徑=====
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5);
        //組成將分塊文件路徑組成 List<ComposeSource>
        List<ComposeSource> sourceObjectList = Stream.iterate(0, i -> ++i)
                .limit(chunkTotal)
                .map(i -> ComposeSource.builder()
                        .bucket(BUCKET_VIDEO)
                        .object(chunkFileFolderPath.concat(Integer.toString(i)))
                        .build())
                .collect(Collectors.toList());
        //=====合并=====
        //文件名稱
        String fileName = uploadFileParamsDto.getFilename();
        //文件擴(kuò)展名
        String extName = fileName.substring(fileName.lastIndexOf("."));
        //合并文件路徑
        String mergeFilePath = getFilePathByMd5(fileMd5, extName);
        try {
            //合并文件
            ObjectWriteResponse response = minioClient.composeObject(
                    ComposeObjectArgs.builder()
                            .bucket(BUCKET_VIDEO)
                            .object(mergeFilePath)
                            .sources(sourceObjectList)
                            .build());
            log.info("合并文件成功:{}",mergeFilePath);
        } catch (Exception e) {
            log.info("合并文件失敗,fileMd5:{},異常:{}",fileMd5,e.getMessage(),e);
            return RestResponse.validfail(false, "合并文件失敗。");
        }

        // ====驗(yàn)證md5====
        File minioFile = downloadFileFromMinIO(BUCKET_VIDEO,mergeFilePath);
        if(minioFile == null){
            log.debug("下載合并后文件失敗,mergeFilePath:{}",mergeFilePath);
            return RestResponse.validfail(false, "下載合并后文件失敗。");
        }

        try (InputStream newFileInputStream = new FileInputStream(minioFile)) {
            //minio上文件的md5值
            String md5Hex = DigestUtils.md5Hex(newFileInputStream);
            //比較md5值,不一致則說明文件不完整
            if(!fileMd5.equals(md5Hex)){
                return RestResponse.validfail(false, "文件合并校驗(yàn)失敗,最終上傳失敗。");
            }
            //文件大小
            uploadFileParamsDto.setFileSize(minioFile.length());
        }catch (Exception e){
            log.debug("校驗(yàn)文件失敗,fileMd5:{},異常:{}",fileMd5,e.getMessage(),e);
            return RestResponse.validfail(false, "文件合并校驗(yàn)失敗,最終上傳失敗。");
        }finally {
            if(minioFile!=null){
                minioFile.delete();
            }
        }

        //文件入庫
        currentProxy.addMediaFilesToDb(companyId,fileMd5,uploadFileParamsDto,BUCKET_VIDEO,mergeFilePath);
        //=====清除分塊文件=====
        clearChunkFiles(chunkFileFolderPath,chunkTotal);
        return RestResponse.success(true);
    }

下載合并文件的方法

    /**
     * 從minio下載文件
     * @param bucket 桶
     * @param objectName 對象名稱
     * @return 下載后的文件
     */
    public File downloadFileFromMinIO(String bucket,String objectName){
        //臨時(shí)文件
        File minioFile = null;
        FileOutputStream outputStream = null;
        try{
            InputStream stream = minioClient.getObject(GetObjectArgs.builder()
                    .bucket(bucket)
                    .object(objectName)
                    .build());
            //創(chuàng)建臨時(shí)文件
            minioFile=File.createTempFile("minio", ".merge");
            outputStream = new FileOutputStream(minioFile);
            IOUtils.copy(stream,outputStream);
            return minioFile;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

清楚分塊文件的方法文章來源地址http://www.zghlxwxcb.cn/news/detail-579564.html

 /**
     * 清除分塊文件
     * @param chunkFileFolderPath 分塊文件路徑
     * @param chunkTotal 分塊文件總數(shù)
     */
    /**
     * 清除分塊文件
     * @param chunkFileFolderPath 分塊文件路徑
     * @param chunkTotal 分塊文件總數(shù)
     */
    private void clearChunkFiles(String chunkFileFolderPath,int chunkTotal){

        try {
            List<DeleteObject> deleteObjects = Stream.iterate(0, i -> ++i)
                    .limit(chunkTotal)
                    .map(i -> new DeleteObject(chunkFileFolderPath.concat(Integer.toString(i))))
                    .collect(Collectors.toList());

            RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket(BUCKET_VIDEO).objects(deleteObjects).build();
            Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);
            results.forEach(r->{
                DeleteError deleteError = null;
                try {
                    deleteError = r.get();
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("清楚分塊文件失敗,objectname:{}",deleteError.objectName(),e);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            log.error("清楚分塊文件失敗,chunkFileFolderPath:{}",chunkFileFolderPath,e);
        }
    }

到了這里,關(guān)于使用MinIO文件存儲系統(tǒng)【完成視頻斷點(diǎn)續(xù)傳】業(yè)務(wù)邏輯的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • SpringBoot整合minio實(shí)現(xiàn)斷點(diǎn)續(xù)傳、分片上傳(附源碼)

    SpringBoot整合minio實(shí)現(xiàn)斷點(diǎn)續(xù)傳、分片上傳(附源碼)

    在Web開發(fā)中,大文件的上傳是必不可少的功能之一。本文將介紹如何使用SpringBoot整合minio實(shí)現(xiàn)一個(gè)簡單的大文件上傳網(wǎng)站。 項(xiàng)目下載 gitee:https://gitee.com/wusupweilgy/springboot-vue.git 前端:vue2、element-ui組件、axios 后端:springboot、minio、mybatis-plus、redis 斷點(diǎn)續(xù)傳 分片上傳 前端顯示

    2024年02月04日
    瀏覽(25)
  • Spring Boot實(shí)現(xiàn)HTTP大文件斷點(diǎn)續(xù)傳分片下載-大視頻分段漸進(jìn)式播放

    服務(wù)端如何將一個(gè)大視頻文件做切分,分段響應(yīng)給客戶端,讓瀏覽器可以漸進(jìn)式地播放。 Spring Boot實(shí)現(xiàn)HTTP分片下載斷點(diǎn)續(xù)傳,從而實(shí)現(xiàn)H5頁面的大視頻播放問題,實(shí)現(xiàn)漸進(jìn)式播放,每次只播放需要播放的內(nèi)容就可以了,不需要加載整個(gè)文件到內(nèi)存中。 文件的斷點(diǎn)續(xù)傳、文件多

    2024年02月14日
    瀏覽(31)
  • Spring Boot整合Minio實(shí)現(xiàn)上傳憑證、分片上傳、秒傳和斷點(diǎn)續(xù)傳

    Spring Boot整合Minio后,前端的文件上傳有兩種方式: 文件上傳到后端,由后端保存到Minio 這種方式好處是完全由后端集中管理,可以很好的做到、身份驗(yàn)證、權(quán)限控制、文件與處理等,并且可以做一些額外的業(yè)務(wù)邏輯,比如生成縮略圖、提取元數(shù)據(jù)等。 缺點(diǎn)也很明顯: 延遲時(shí)

    2024年02月04日
    瀏覽(24)
  • Spring-Boot實(shí)現(xiàn)HTTP大文件斷點(diǎn)續(xù)傳分片下載-大視頻分段漸進(jìn)式播放

    服務(wù)端如何將一個(gè)大視頻文件做切分,分段響應(yīng)給客戶端,讓瀏覽器可以漸進(jìn)式地播放。 Spring Boot實(shí)現(xiàn)HTTP分片下載斷點(diǎn)續(xù)傳,從而實(shí)現(xiàn)H5頁面的大視頻播放問題,實(shí)現(xiàn)漸進(jìn)式播放,每次只播放需要播放的內(nèi)容就可以了,不需要加載整個(gè)文件到內(nèi)存中。 文件的斷點(diǎn)續(xù)傳、文件多

    2024年02月11日
    瀏覽(31)
  • 對視頻進(jìn)行分塊,斷點(diǎn)續(xù)傳

    對視頻進(jìn)行分塊,斷點(diǎn)續(xù)傳

    ?分塊測試 將視頻分塊成1mb一份的文件? 將分塊的視頻重新合并

    2024年02月20日
    瀏覽(17)
  • Java文件斷點(diǎn)續(xù)傳

    斷點(diǎn)續(xù)傳實(shí)現(xiàn)思路:將大文件均分成幾塊后,每個(gè)線程分別處理一塊數(shù)據(jù)的讀取和寫入。每次寫入都要更新記錄的日志文件,斷網(wǎng)或暫定后重新開始傳輸時(shí),根據(jù)日志文件的信息,可以接著讀取寫入數(shù)據(jù),不用重頭開始傳輸。

    2024年02月12日
    瀏覽(21)
  • Java實(shí)現(xiàn)文件斷點(diǎn)續(xù)傳

    文件斷點(diǎn)續(xù)傳代碼 測試代碼

    2024年03月09日
    瀏覽(27)
  • 前端文件上傳(文件上傳,分片上傳,斷點(diǎn)續(xù)傳)

    前端文件上傳(文件上傳,分片上傳,斷點(diǎn)續(xù)傳)

    普通文件上傳 思路: 首先獲取用戶選擇的文件對象,并將其添加到一個(gè) FormData 對象中。然后,使用 axios 的 post 方法將 FormData 對象發(fā)送到服務(wù)器。在 then 和 catch 中,我們分別處理上傳成功和失敗的情況,并輸出相應(yīng)的信息。 需要注意,在使用 axios 進(jìn)行文件上傳時(shí),必須將

    2024年02月22日
    瀏覽(30)
  • 【項(xiàng)目實(shí)戰(zhàn)】大文件斷點(diǎn)續(xù)傳,搞起

    【項(xiàng)目實(shí)戰(zhàn)】大文件斷點(diǎn)續(xù)傳,搞起

    今天給大家分享的又是一篇實(shí)戰(zhàn)文章,也是最近私活里遇到的,萬能的互聯(lián)網(wǎng)給了我辦法,分享一下。 最近接到一個(gè)新的需求,需要上傳 2G 左右的視頻文件,用測試環(huán)境的 OSS 試了一下,上傳需要十幾分鐘,再考慮到公司的資源問題,果斷放棄該方案。 一提到大文件上傳,

    2024年02月12日
    瀏覽(25)
  • 1. 大文件上傳如何斷點(diǎn)續(xù)傳

    文件分片 - 將文件分割成多個(gè)小塊,以便于上傳和管理。 計(jì)算文件以及分片文件的Hash值 - 生成唯一標(biāo)識符 - 通過計(jì)算文件及其分片的Hash值來創(chuàng)建一個(gè)唯一的標(biāo)識符。 上傳分片 - 根據(jù)標(biāo)識符判斷分片文件上傳狀態(tài) - 避免重復(fù)上傳。 如果上傳中斷,下次上傳時(shí)根據(jù)標(biāo)識符跳過

    2024年04月22日
    瀏覽(23)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包