广告
返回顶部
首页 > 资讯 > 精选 >怎么通过Java实现文件断点续传功能
  • 822
分享到

怎么通过Java实现文件断点续传功能

2023-06-30 15:06:06 822人浏览 薄情痞子
摘要

这篇文章主要介绍“怎么通过Java实现文件断点续传功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么通过Java实现文件断点续传功能”文章能帮助大家解决问题。什么是断点续传用户上传大文件,网络差

这篇文章主要介绍“怎么通过Java实现文件断点续传功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么通过Java实现文件断点续传功能”文章能帮助大家解决问题。

什么是断点续传

用户上传大文件,网络差点的需要历时数小时,万一线路中断,不具备断点续传的服务器就只能从头重传,而断点续传就是,允许用户从上传断线的地方继续传送,这样大大减少了用户的烦恼。

  • 解决上传大文件服务器内存不够的问题

  • 解决如果因为其他因素导致上传终止的问题,并且刷新浏览器后仍然能够续传,重启浏览器(关闭浏览器后再打开)仍然能够继续上传,重启电脑后仍然能够上传

  • 检测上传过程中因网络波动导致文件出现了内容丢失那么需要自动检测并且从新上传

解决方案

前端

  • 需要进行分割上传的文件

  • 需要对上传的分片文件进行指定文件序号

  • 需要监控上传进度,控制进度条

  • 上传完毕后需要发送合并请求

Blob 对象,操作文件

后端

  • 上传分片的接口

  • 合并分片的接口

  • 获取分片的接口

  • 其他工具方法,用于辅助

前端端需要注意的就是: 文件的切割,和进度条

后端需要注意的就是: 分片存储的地方和如何进行合并分片

效果演示

先找到需要上传的文件

怎么通过Java实现文件断点续传功能

当我们开始上传进度条就会发生变化,当我们点击停止上传那么进度条就会停止

怎么通过Java实现文件断点续传功能

我们后端会通过文件名+文件大小进行MD5生成对应的目录结果如下:

怎么通过Java实现文件断点续传功能

当前端上传文件达到100%时候就会发送文件合并请求,然后我们后端这些分片都将被合并成一个文件

怎么通过Java实现文件断点续传功能

通过下图可以看到所有分片都没有了,从而合并出来一个文件

怎么通过Java实现文件断点续传功能

以上就是断点续传的核心原理,但是还需处理一些异常情况:

  • 文件上传过程中网络波动导致流丢失一部分(比对大小)

  • 文件上传过程中,服务器丢失分片 (比对分片的连续度)

  • 文件被篡改内容(比对大小)

效验核心代

怎么通过Java实现文件断点续传功能

参考代码

前端

<!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>    <h2>HTML5大文件断点切割上传</h2>    <div id="progressBar"></div>    <input id="file" name="mov" type="file" />    <input id="btn" type="button" value="点我上传" />    <input id="btn1" type="button" value="点我停止上传" />    <script type="module">        import FileSliceUpload  from '../jsutils/FileSliceUpload.js'        let testingUrl="http://localhost:7003/fileslice/testing"        let uploadUrl="http://localhost:7003/fileslice/uploads"        let margeUrl="http://localhost:7003/fileslice/merge-file-slice"        let progressUrl="http://localhost:7003/fileslice/progress"         let fileSliceUpload=  new FileSliceUpload(testingUrl,uploadUrl,margeUrl,progressUrl,"#file")         fileSliceUpload.addProgress("#progressBar")          let btn=  document.querySelector("#btn")          let btn1=  document.querySelector("#btn1")        btn.addEventListener("click",function () {            fileSliceUpload.startUploadFile()        })        btn1.addEventListener("click",function () {            fileSliceUpload.stopUploadFile()        })    </script></body></html>
//大文件分片上传,比如10G的压缩包,或者视频等,这些文件太大了  (需要后端配合进行)class FileSliceUpload{         constructor(testingUrl, uploadUrl, margeUrl,progressUrl, fileSelect) {            this.testingUrl = testingUrl; // 检测文件上传的url            this.uploadUrl = uploadUrl;//文件上传接口            this.margeUrl = margeUrl; // 合并文件接口            this.progressUrl = progressUrl; //进度接口            this.fileSelect = fileSelect;            this.fileObj = null;            this.totalize = null;            this.blockSize = 1024 * 1024; //每次上传多少字节1mb(最佳)            this.sta = 0; //起始位置            this.end =  this.sta +  this.blockSize; //结束位置            this.count = 0; //分片个数            this.barId = "bar"; //进度条id            this.progressId = "progress";//进度数值ID            this.fileSliceName = ""; //分片文件名称            this.fileName = "";            this.uploadFileInterval = null;  //上传文件定时器    }        addProgress (progressSelect) {        let bar = document.createElement("div")        bar.setAttribute("id", this.barId);        let num = document.createElement("div")        num.setAttribute("id", this.progressId);        num.innerText = "0%"        bar.appendChild(num);        document.querySelector(progressSelect).appendChild(bar)         }    //续传  在上传前先去服务器检测之前是否有上传过这个文件,如果还有返回上传的的分片,那么进行续传    // 将当前服务器上传的最后一个分片会从新上传, 避免因为网络的原因导致分片损坏     sequelFile () {        if (this.fileName) {            var xhr = new XMLHttpRequest();            //同步            xhr.open('GET', this.testingUrl + "/" + this.fileName+ "/" + this.blockSize+ "/" + this.totalize, false);            xhr.send();            if (xhr.readyState === 4 && xhr.status === 200) {                let ret = JSON.parse(xhr.response)                if (ret.code == 20000) {                   let data= ret.data                    this.count = data.code;                    this.fileSliceName = data.fileSliceName                    //计算起始位置和结束位置                    this.sta = this.blockSize * this.count                    //计算结束位置                    this.end = this.sta + this.blockSize                } else {                    this.sta = 0; //从头开始                    this.end = this.sta + this.blockSize;                    this.count = 0; //分片个数                }            }        }    }    stopUploadFile () {        clearInterval(this.uploadFileInterval)    }    // 文件上传(单文件)    startUploadFile () {          // 进度条         let bar = document.getElementById(this.barId)         let progressEl = document.getElementById(this.progressId)        this.fileObj = document.querySelector(this.fileSelect).files[0];        this.totalize = this.fileObj.size;        this.fileName = this.fileObj.name;         //查询是否存在之前上传过此文件,然后继续        this.sequelFile()        let ref = this; //拿到当前对象的引用,因为是在异步中使用this就是他本身而不是class        this.uploadFileInterval = setInterval(function () {                if (ref.sta > ref.totalize) {                    //上传完毕后结束定时器                    clearInterval(ref.uploadFileInterval)                    //发送合并请求                    ref.margeUploadFile ()                    console.log("stop" + ref.sta);                    return;                };                //分片名称                ref.fileSliceName = ref.fileName + "-slice-" + ref.count++                //分割文件 ,                var blob1 =  ref.fileObj.slice(ref.sta, ref.end);                var fd = new FORMData();                fd.append('part', blob1);                fd.append('fileSliceName', ref.fileSliceName);                fd.append('fileSize', ref.totalize);                var xhr = new XMLHttpRequest();                xhr.open('POST',  ref.uploadUrl, true);                xhr.send(fd); //异步发送文件,不管是否成功, 会定期检测                xhr.onreadystatechange = function () {                    if (xhr.readyState === 4 && xhr.status === 200) {                        let ret = JSON.parse(xhr.response)                        if (ret.code == 20000) {                            //计算进度                            let percent =  Math.ceil((ret.data*ref.blockSize/ ref.totalize) * 100)                            if (percent > 100) {                                percent=100                                                            }                            bar.style.width = percent + '%';                            bar.style.backgroundColor = 'red';                            progressEl.innerHTML = percent + '%'                        }                    }            }            //起始位置等于上次上传的结束位置            ref.sta =  ref.end;            //结束位置等于上次上传的结束位置+每次上传的字节            ref.end = ref.sta + ref.blockSize;                }, 5)    }    margeUploadFile () {            console.log("检测上传的文件完整性..........");            var xhr = new XMLHttpRequest();            //文件分片的名称/分片大小/总大小            xhr.open('GET', this.margeUrl+ "/" + this.fileSliceName + "/" + this.blockSize + "/" + this.totalize, true);            xhr.send(); //发送请求            xhr.onreadystatechange = function () {                if (xhr.readyState === 4 && xhr.status === 200) {                    let ret = JSON.parse(xhr.response)                    if (ret.code == 20000) {                        console.log("文件上传完毕");                    } else {                        console.log("上传完毕但是文件上传过程中出现了异常", ret);                    }                }            }        }}export default FileSliceUpload;

后端

因为代码内部使用较多自己封装的工具类的原因,以下代码只提供原理的参考

package com.controller.commontools.fIleupload;import com.alibaba.fastjson.JSON;import com.application.Result;import com.container.ArrayByteUtil;import com.encryption.hash.HashUtil;import com.file.FileUtils;import com.file.FileWEBUpload;import com.file.ReadWriteFileUtils;import com.function.impl.ExecutorUtils;import com.path.ResourceFileUtil;import com.string.PatternCommon;import org.springframework.web.bind.annotation.*;import javax.servlet.http.httpservletRequest;import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandoMaccessFile;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.concurrent.Future;import java.util.concurrent.atomic.AtomicBoolean;import java.util.stream.Collectors;@RestController@RequestMapping("/fileslice")public class FIleSliceUploadController {    private  final  String identification="-slice-";    private  final  String uploadslicedir="uploads"+File.separator+"slice"+File.separator;//分片目录    private  final  String uploaddir="uploads"+File.separator+"real"+File.separator;//实际文件目录    //获取分片    @GetMapping("/testing/{fileName}/{fileSlicSize}/{fileSize}")    public Result testing(@PathVariable String fileName,@PathVariable long fileSlicSize,@PathVariable long fileSize  ) throws Exception {        String dir = fileNameMd5Dir(fileName,fileSize);        String absoluteFilePathAndCreate = ResourceFileUtil.getAbsoluteFilePathAndCreate(uploadslicedir)+File.separator+dir;        File file = new File(absoluteFilePathAndCreate);        if (file.exists()) {            List<String> filesAll = FileUtils.getFilesAll(file.getAbsolutePath());            if (filesAll.size()<2){                //分片缺少 删除全部分片文件 ,从新上传                FileUtils.delFilesAllReview(absoluteFilePathAndCreate,true);                return Result.Error();            }            //从小到大文件进行按照序号排序,和判断分片是否损坏            List<String> collect = fileSliceIsbadAndSort(file, fileSlicSize);            //获取最后一个分片            String fileSliceName = collect.get(collect.size() - 1);            fileSliceName = new File(fileSliceName).getName();            int code = fileId(fileSliceName);            //服务器的分片总大小必须小于或者等于文件的总大小            if ((code*fileSlicSize)<=fileSize) {                Result result = new Result();                String finalFileSliceName = fileSliceName;                String str = PatternCommon.renderString("{\"code\":\"$[code]\",\"fileSliceName\":\"${fileSliceName}\"}", new HashMap<String, String>() {{                    put("code", String.valueOf(code));                    put("fileSliceName", finalFileSliceName);                }});                result.setData(JSON.parse(str));                return result;            }else {                //分片异常 ,删除全部分片文件,从新上传                FileUtils.delFilesAllReview(absoluteFilePathAndCreate,true);                return Result.Error();            }        }        //不存在       return Result.Error();    }    @PostMapping(value = "/uploads")    public Result uploads(HttpServletRequest request)  {        String fileSliceName = request.getParameter("fileSliceName");        long fileSize = Long.parseLong(request.getParameter("fileSize")); //文件大小        String dir = fileSliceMd5Dir(fileSliceName,fileSize);        String absoluteFilePathAndCreate = ResourceFileUtil.getAbsoluteFilePathAndCreate(uploadslicedir+dir);        FileWebUpload.fileUpload(absoluteFilePathAndCreate,fileSliceName,request);        int i = fileId(fileSliceName); //返回上传成功的文件id,用于前端计算进度        Result result=new Result();        result.setData(i);        return result;    }    // 合并分片    @GetMapping(value = "/merge-file-slice/{fileSlicNamee}/{fileSlicSize}/{fileSize}")    public Result mergeFileSlice(@PathVariable String fileSlicNamee,@PathVariable long fileSlicSize,@PathVariable long fileSize ) throws Exception {        int l =(int) Math.ceil((double) fileSize / fileSlicSize); //有多少个分片        String dir = fileSliceMd5Dir(fileSlicNamee,fileSize); //分片所在的目录       String absoluteFilePathAndCreate = ResourceFileUtil.getAbsoluteFilePathAndCreate(uploadslicedir+dir);        File file=new File(absoluteFilePathAndCreate);        if (file.exists()){            List<String> filesAll = FileUtils.getFilesAll(file.getAbsolutePath());            //阻塞循环判断是否还在上传  ,解决前端进行ajax异步上传的问题            int beforeSize=filesAll.size();            while (true){                 Thread.sleep(1000);                 //之前分片数量和现在分片数据只差,如果大于1那么就在上传,那么继续                 filesAll = FileUtils.getFilesAll(file.getAbsolutePath());                if (filesAll.size()-beforeSize>=1){                    beforeSize=filesAll.size();                    //继续检测                    continue;                }                //如果是之前分片和现在的分片相等的,那么在阻塞2秒后检测是否发生变化,如果还没变化那么上传全部完成,可以进行合并了                //当然这不是绝对的,只能解决网络短暂的波动,因为有可能发生断网很长时间,网络恢复后文件恢复上传, 这个问题是避免不了的,所以我们在下面的代码进行数量的效验                // 因为我们不可能一直等着他网好,所以如果1~3秒内没有上传新的内容,那么我们默认判定上传完毕                if (beforeSize==filesAll.size()){                    Thread.sleep(2000);                    filesAll = FileUtils.getFilesAll(file.getAbsolutePath());                    if (beforeSize==filesAll.size()){                        break;                    }                }            }            //分片数量效验            if (filesAll.size()!=l){                //分片缺少 ,删除全部分片文件,从新上传                FileUtils.delFilesAllReview(absoluteFilePathAndCreate,true);                return Result.Error();            }            //获取实际的文件名称,组装路径            String realFileName = realFileName(fileSlicNamee);            String realFileNamePath = ResourceFileUtil.getAbsoluteFilePathAndCreate(uploaddir+ realFileName);            //从小到大文件进行按照序号排序 ,和检查分片文件是否有问题            List<String> collect = fileSliceIsbadAndSort(file, fileSlicSize);            int fileSliceSize = collect.size();            List<Future<?>> futures = new ArrayList<>();            // 将文件按照序号进行合并 ,算出Runtime.getRuntime().availableProcessors()个线程 ,每个线程需要读取多少分片, 和每个线程需要读取多少字节大小            //有人会说一个分片一个线程不行吗,你想想如果上千或者上万分片的话,你创建这么多的线程需要多少时间,以及线程切换上下文切换和销毁需要多少时间?             // 就算使用线程池,也顶不住啊,你内存又有多大,能存下多少队列?,并发高的话直接怼爆            int availableProcessors = Runtime.getRuntime().availableProcessors();            //每个线程读取多少文件            int readFileSize = (int)Math.ceil((double)fileSliceSize / availableProcessors);            //每个线程需要读取的文件大小            long readSliceSize = readFileSize * fileSlicSize;            for (int i = 0; i < availableProcessors; i++) {                int finalI = i;                Future<?> future =   ExecutorUtils.createFuture("FIleSliceUploadController",()->{                    //每个线程需要读取多少字节                    byte[] bytes=new byte[(int) readSliceSize];                    int index=0;                    for (int i1 = finalI *readFileSize,i2 = readFileSize*(finalI+1)>fileSliceSize?fileSliceSize:readFileSize*(finalI+1); i1 < i2; i1++) {                        try ( RandomAccessFile r = new RandomAccessFile(collect.get(i1), "r");){                            r.read(bytes, (int)(index*fileSlicSize),(int)fileSlicSize);                        } catch (IOException e) {                            e.printStackTrace();                        }                        index++;                    }                    if(finalI==availableProcessors-1){                        //需要调整数组                        bytes = ArrayByteUtil.getActualBytes(bytes);                    }                    try ( RandomAccessFile w = new RandomAccessFile(realFileNamePath, "rw");){                        //当前文件写入的位置                        w.seek(finalI*readSliceSize);                        w.write(bytes);                    } catch (IOException e) {                        e.printStackTrace();                    }                });                futures.add(future);            }            //阻塞到全部线程执行完毕后            ExecutorUtils.waitComplete(futures);            //删除全部分片文件            FileUtils.delFilesAllReview(absoluteFilePathAndCreate,true);        }else {            //没有这个分片相关的的目录            return Result.Error();        }        return Result.Ok();    }    //获取分片文件的目录    private String fileSliceMd5Dir(String fileSliceName,long fileSize){        int i = fileSliceName.indexOf(identification) ;        String substring = fileSliceName.substring(0, i);        String dir = HashUtil.md5(substring+fileSize);        return dir;    }    //通过文件名称获取文件目录    private String fileNameMd5Dir(String fileName,long fileSize){        return HashUtil.md5(fileName+fileSize);    }    //获取分片的实际文件名    private String realFileName(String fileSliceName){        int i = fileSliceName.indexOf(identification) ;        String substring = fileSliceName.substring(0, i);        return substring;    }    //获取文件序号    private  int fileId(String fileSliceName){        int i = fileSliceName.indexOf(identification)+identification.length() ;        String fileId = fileSliceName.substring(i);        return Integer.parseInt(fileId);    }  //判断是否损坏  private List<String>  fileSliceIsbadAndSort(File file,long fileSlicSize) throws Exception {        String absolutePath = file.getAbsolutePath();        List<String> filesAll = FileUtils.getFilesAll(absolutePath);        if (filesAll.size()<1){            //分片缺少,删除全部分片文件 ,从新上传            FileUtils.delFilesAllReview(absolutePath,true);            throw  new Exception("分片损坏");        }        //从小到大文件进行按照序号排序        List<String> collect = filesAll.stream().sorted((a, b) -> fileId(a) - fileId(b)).collect(Collectors.toList());        //判断文件是否损坏,将文件排序后,进行前后序号相差大于1那么就代表少分片了        for (int i = 0; i < collect.size()-1; i++) {            //检测分片的连续度            if (fileId(collect.get(i)) - fileId(collect.get(i+1))!=-1) {                //分片损坏 删除全部分片文件 ,从新上传                FileUtils.delFilesAllReview(absolutePath,true);                throw  new Exception("分片损坏");            }            //检测分片的完整度            if (new File(collect.get(i)).length()!=fileSlicSize) {                //分片损坏 删除全部分片文件 ,从新上传                FileUtils.delFilesAllReview(absolutePath,true);                throw  new Exception("分片损坏");            }        }        return  collect;    }}

关于“怎么通过Java实现文件断点续传功能”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网精选频道,小编每天都会为大家更新不同的知识点。

--结束END--

本文标题: 怎么通过Java实现文件断点续传功能

本文链接: https://www.lsjlt.com/news/329749.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么通过Java实现文件断点续传功能
    这篇文章主要介绍“怎么通过Java实现文件断点续传功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么通过Java实现文件断点续传功能”文章能帮助大家解决问题。什么是断点续传用户上传大文件,网络差...
    99+
    2023-06-30
  • 通过Java实现文件断点续传功能
    目录什么是断点续传解决方案效果演示参考代码前端后端什么是断点续传 用户上传大文件,网络差点的需要历时数小时,万一线路中断,不具备断点续传的服务器就只能从头重传,而断点续传就是,允许用...
    99+
    2022-11-13
  • Java中怎么实现断点续传功能
    这篇文章给大家介绍Java中怎么实现断点续传功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。(一)断点续传的原理   其实断点续传的原理很简单,就是在Http的请求上和一般的下载有所不同而已。   打个比方,浏览器请...
    99+
    2023-06-03
  • HTML5如何实现文件断点续传功能
    这篇文章主要为大家展示了“HTML5如何实现文件断点续传功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“HTML5如何实现文件断点续传功能”这篇文章吧。HTM...
    99+
    2022-10-19
  • java实现文件的断点续传
    所谓文件的断点续传,就是一个线程传输文件,另一个线程控制传输标识,以达到暂停文件效果、恢复文件上传的效果。 本demo使用最基本的线程之间的通信来实现一个简单的断点续传。 packa...
    99+
    2022-11-13
  • C#中怎么实现断点续传功能
    本篇文章为大家展示了C#中怎么实现断点续传功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。以下是一个请求报文与相应的回复报文的例子:GET /image/index_r4_c1.jpg&...
    99+
    2023-06-17
  • java实现多线程文件的断点续传
    java文件的多线程断点续传大致原理,供大家参考,具体内容如下 谈到文件断点续传那么就离不开java.io.RandomAcessFile HttpUrlConnection类 大致...
    99+
    2022-11-13
  • android怎么实现多线程断点续传功能
    这篇文章主要介绍了android怎么实现多线程断点续传功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。具体内容如下布局:<xml version="...
    99+
    2023-05-30
    android 多线程
  • Java实现断点续传功能的示例代码
    目录一、题目描述二、解题思路三、代码详解一、题目描述 题目实现:网络资源的断点续传功能。 二、解题思路 获取要下载的资源网址 显示网络资源的大小 上次读取到的字节位置以及未读取的字节...
    99+
    2022-11-13
    Java实现断点续传 Java断点续传
  • Python 工具类实现大文件断点续传功能详解
    依赖 os、sys、requests 工具代码 废话不多说,上代码。 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Cre...
    99+
    2022-11-12
  • Vue+Node怎么实现大文件上传和断点续传
    本篇内容介绍了“Vue+Node怎么实现大文件上传和断点续传”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!源代码断点续传、分片上传、秒传、重...
    99+
    2023-06-30
  • C#怎样实现文件下载断点续传
    目录前言文件下载-服务端使用a标签提供文件下载使用Response.TransmitFile提供文件下载其他方式文件下载文件下载-客户端直接下载异步下载断点续传断点续传(服务端的支持...
    99+
    2022-11-12
  • 前端开发怎么实现文件的断点续传
    本篇内容介绍了“前端开发怎么实现文件的断点续传”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!早就听说过断点...
    99+
    2022-10-19
  • vue怎么实现大文件分片上传与断点续传送
    本文小编为大家详细介绍“vue怎么实现大文件分片上传与断点续传送”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue怎么实现大文件分片上传与断点续传送”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。问题:前段时间...
    99+
    2023-07-02
  • java如何实现文件切片上传服务器+断点续传
    这篇文章主要为大家展示了“java如何实现文件切片上传服务器+断点续传”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“java如何实现文件切片上传服务器+断点续传”这篇文章吧。1.定义一个实体类用...
    99+
    2023-06-22
  • Android中使用Socket怎么实现文件断点上传功能
    今天就跟大家聊聊有关Android中使用Socket怎么实现文件断点上传功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。什么是Socket所谓Socket通常也称作“套接字”,用于...
    99+
    2023-05-31
    android socket roi
  • java实现文件切片上传百度云+断点续传的方法
    前言: 本文代码通过dubbo进行远程调用的接口,如果不使用dubbo,直接将service放到你的service,并稍作修改,redis替换成自己封装的工具即可。下方代码有点多,但...
    99+
    2022-11-12
  • Android中怎么利用FTP实现多线程断点续传下载上传功能
    Android中怎么利用FTP实现多线程断点续传下载上传功能,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。FTP下载原理FTP单线程断点续传FTP和传统的HTT...
    99+
    2023-05-30
    android
  • java怎么实现文件夹上传功能
    这篇文章主要介绍“java怎么实现文件夹上传功能”,在日常操作中,相信很多人在java怎么实现文件夹上传功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java怎么实现文件夹上传功能”的疑惑有所帮助!接下来...
    99+
    2023-07-05
  • java怎么实现文件的上传功能
    今天小编给大家分享一下java怎么实现文件的上传功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、上传界面<%@&...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作