阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

基于RMI服务传输大文件的完整解决方案

97次阅读
没有评论

共计 16318 个字符,预计需要花费 41 分钟才能阅读完成。

基于 RMI 服务传输大文件,分为上传和下载两种操作,需要注意的技术点主要有三方面,第一,RMI 服务中传输的数据必须是可序列化的。第二,在传输大文件的过程中应该有进度提醒机制,对于大文件传输来说,这点很重要,因为大文件的传输时间周期往往比较长,必须实时告知用户大文件的传输进度。第三,针对大文件的读取方式,如果采用一次性将大文件读取到 byte[]中是不现实的,因为这将受制于 JVM 的可用内存,会导致内存溢出的问题。

笔者实验的基于 RMI 服务传输大文件的解决方案,主要就是围绕以上三方面进行逐步解决的。下面将分别就上传大文件和下载大文件进行阐述。

1. 基于 RMI 服务上传大文件

1.1. 设计思路

上传大文件分为两个阶段,分别为“CS 握手阶段”和“文件内容上传更新阶段”。

CS 握手阶段,又可称之为客户端与服务端之间的基本信息交换阶段。客户端要确定待上传的本地文件和要上传到服务端的目标路径。读取本地文件,获取文件长度,将本地文件长度、本地文件路径和服务端目标路径等信息通过接口方法传递到服务端,然后由服务端生成具有唯一性的 FileKey 信息,并返回到客户端,此 FileKey 作为客户端与服务端之间数据传输通道的唯一标示。这些信息数据类型均为 Java 基本数据类型,因此都是可序列化的。此接口方法就称之为“握手接口”,通过 CS 握手,服务端能确定三件事:哪个文件要传输过来、这个文件的尺寸、这个文件将存放在哪里,而这三件刚好是完成文件上传的基础。

然后就是“文件内容上传更新阶段”。客户端打开文件后,每次读取一定量的文件内容,譬如每次读取(1024 * 1024 * 2)byte 的数据,并将此批数据通过“上传更新”接口方法传输到服务端,由服务端写入输出流中,同时检查文件内容是否已经传输完毕,如果已经传输完毕,则执行持久化 flush 操作在服务端生成文件;客户端每次传输一批数据后,就更新“已传输数据总量”标示值,并与文件总长度进行比对计算,从而得到文件上传进度,实时告知用户。综上所述,客户端循环读取本地文件内容并传输到服务端,直到文件内容读取上传完毕为止。

1.2. 功能设计

1.2.1 文件上传相关状态信息的管理

大文件上传的过程中,在服务端,最重要的是文件上传过程相关状态信息的精确管理,譬如,文件总长度、已上传字节总数、文件存储路径等等。而且要保证在整个上传过程中数据的实时更新和绝对不能丢失,并且在文件上传完毕后及时清除这些信息,以避免服务端累计过多失效的状态数据。

鉴于此,我们设计了一个类 RFileUploadTransfer 来实现上述功能。代码如下:

/**
 * Description: 文件上传过程相关状态信息封装类。<br>
 * Copyright: Copyright (c) 2016<br>
 * Company: 河南电力科学研究院智能电网所 <br>
 * @author shangbingbing 2016-01-01 编写
 * @version 1.0
 */
public class RFileUploadTransfer implements Serializable {
    private static final long serialVersionUID = 1L;
    private String fileKey;
    // 客户端文件路径
    private String srcFilePath;
    // 服务端上传目标文件路径
    private String destFilePath;
    // 文件尺寸
    private int fileLength = 0;
    // 已传输字节总数
    private int transferByteCount = 0;
    // 文件是否已经完整写入服务端磁盘中
    private boolean isSaveFile = false;
    private OutputStream out = null;
   
    public RFileUploadTransfer(String srcFilePath, int srcFileLength, String destFilePath) {
        this.fileKey = UUID.randomUUID().toString();
        this.srcFilePath = srcFilePath;
        this.fileLength = srcFileLength;
        this.destFilePath = destFilePath;
       
        File localFile = new File(this.destFilePath);
        if(localFile.getParentFile().exists() == false) {
            localFile.getParentFile().mkdirs();
        }
        try {
            this.out = new FileOutputStream(localFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
   
    public String getFileKey() {
        return fileKey;
    }
    public String getSrcFilePath() {
        return srcFilePath;
    }
    public String getDestFilePath() {
        return destFilePath;
    }
    public boolean isSaveFile() {
        return isSaveFile;
    }
   
    public void addContentBytes(byte[] bytes) {
        try {
            if(bytes == null || bytes.length == 0) {
                return;
            }
            if(this.transferByteCount + bytes.length > this.fileLength) {
                // 如果之前已经传输的数据长度 + 本批数据长度 > 文件长度的话,说明这批数据是最后一批数据了;
                // 由于本批数据中可能会存在有空字节,所以需要筛选出来。
                byte[] contents = new byte[this.fileLength – this.transferByteCount];
                for(int i=0;i<contents.length;i++) {
                    contents[i] = bytes[i];
                }
                this.transferByteCount = this.fileLength;
                this.out.write(contents);
            } else {
                // 说明本批数据并非最后一批数据,文件还没有传输完。
                this.transferByteCount += bytes.length;
                this.out.write(bytes);
            }
            if(this.transferByteCount >= this.fileLength) {
                this.out.flush();
                this.isSaveFile = true;
                if(this.out != null) {
                    try {
                        this.out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

然后,在 RMI 服务接口方法实现类中构建一个线程安全的集合,用来存储管理各个大文件的传输过程,代码如下:

/**
* 上传文件状态监视器
*/
private Hashtable<String,RFileUploadTransfer> uploadFileStatusMonitor = new Hashtable<String,RFileUploadTransfer>();

1.2.2 CS 握手接口设计

CS 握手接口名称为 startUploadFile,主要功能就是传输交换文件基本信息,构建文件上传过程状态控制对象。其在接口实现类中的代码如下所示:

@Override
public String startUploadFile(String localFilePath, int localFileLength, String remoteFilePath) throws RemoteException {
    RFileUploadTransfer fileTransfer = new RFileUploadTransfer(localFilePath,localFileLength,remoteFilePath);
    if(this.uploadFileStatusMonitor.containsKey(fileTransfer.getFileKey())) {
        this.uploadFileStatusMonitor.remove(fileTransfer.getFileKey());
    }
    this.uploadFileStatusMonitor.put(fileTransfer.getFileKey(), fileTransfer);
    return fileTransfer.getFileKey();
}

1.2.3 文件内容上传更新接口设计
文件内容上传更新接口名称为 updateUploadProgress,主要功能是接收客户端传输过来的文件内容 byte[]信息。其在接口实现类中的代码如下所示:

@Override
public boolean updateUploadProgress(String fileKey, byte[] contents) throws RemoteException {
    if(this.uploadFileStatusMonitor.containsKey(fileKey)) {
        RFileUploadTransfer fileTransfer = this.uploadFileStatusMonitor.get(fileKey);
        fileTransfer.addContentBytes(contents);
        if(fileTransfer.isSaveFile()) {
            this.uploadFileStatusMonitor.remove(fileKey);
        }
    }
    return true;
}

1.2.4 客户端设计

客户端的主要功能是打开本地文件,按批读取文件内容 byte[]信息,调用 RMI 接口方法进行传输,同时进行传输进度的提醒。下面是笔者本人采用 swing 开发的测试代码,采用 JProgressBar 进行进度的实时提醒。

progressBar.setMinimum(0);
progressBar.setMaximum(100);
InputStream is = null;
try {
    File srcFile = new File(localFilePath);
    int fileSize = (int)srcFile.length();
    String fileKey = getFileManageService().startUploadFile(localFilePath, fileSize, remoteFilePath);
                           
    byte[] buffer = new byte[1024 * 1024 * 2];
    int offset = 0;
    int numRead = 0;
    is = new FileInputStream(srcFile);
    while(-1 != (numRead=is.read(buffer))) {
        offset += numRead;
        getFileManageService().updateUploadProgress(fileKey, buffer);
        double finishPercent = (offset * 1.0 / fileSize) * 100;
        progressBar.setValue((int)finishPercent);
    }
    if(offset != fileSize) {
        throw new IOException(“ 不能完整地读取文件 ” + localFilePath);
    } else {
        progressBar.setValue(100);
    }
} catch (Exception ex) {
    ex.printStackTrace();
} finally {
    try {
        if(is != null) {
            is.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

实例界面截图如下所示:

基于 RMI 服务传输大文件的完整解决方案

更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2016-02/128710p2.htm

2. 基于 RMI 服务下载大文件

2.1. 设计思路

下载大文件分为两个阶段,分别为“CS 握手阶段”和“文件内容下载更新阶段”。

CS 握手阶段,又可称之为客户端与服务端之间的基本信息交换阶段。服务端读取待下载的文件,获取文件长度,生成具有唯一性的 FileKey 信息,并将文件长度、FileKey 信息传输到客户端,此 FileKey 作为客户端与服务端之间数据传输通道的唯一标示。这些信息数据类型均为 Java 基本数据类型,因此都是可序列化的。此接口方法就称之为“握手接口”,通过 CS 握手,客户端能确定两件事:哪个文件要下载、这个文件的尺寸,而这两件刚好是完成文件下载的基础。

然后就是“文件内容下载更新阶段”。服务端打开文件后,每次读取一定量的文件内容,譬如每次读取(1024 * 1024 * 2)byte 的数据,并将此批数据通过“下载更新”接口方法传输到客户端,由客户端写入输出流中,同时检查文件内容是否已经传输完毕,如果已经传输完毕,则执行持久化 flush 操作在客户端生成文件;客户端每接收一批数据后,就更新“已下载数据总量”标示值,并与文件总长度进行比对计算,从而得到文件下载进度,实时告知用户。综上所述,客户端循环获取服务端传输过来的文件内容,直到服务端文件内容读取传输完毕为止。

2.2. 功能设计

2.2.1 文件下载相关状态信息的管理

大文件下载的过程中,在服务端,最重要的是文件下载过程相关状态信息的精确管理,譬如,文件总长度、已下载字节总数等等。而且要保证在整个下载过程中数据的实时更新和绝对不能丢失,并且在文件下载完毕后及时清除这些信息,以避免服务端累计过多失效的状态数据。

鉴于此,我们设计了一个类 RFileDownloadTransfer 来实现上述功能。代码如下:

/**
 * Description: 文件下载过程相关状态信息封装类。<br>
 * Copyright: Copyright (c) 2016<br>
 * Company: 河南电力科学研究院智能电网所 <br>
 * @author shangbingbing 2016-01-01 编写
 * @version 1.0
 */
public class RFileDownloadTransfer implements Serializable {
    private static final long serialVersionUID = 1L;
    private String fileKey;
    // 服务端待下载文件路径
    private String srcFilePath;
    // 待下载文件尺寸
    private int fileLength = 0;
    private InputStream inputStream = null;
    // 已经传输文件内容字节总数
    private int transferByteCount = 0;
    // 服务端待下载文件是否已经读取完毕
    private boolean isReadFinish = false;
   
    public RFileDownloadTransfer(String srcFilePath) {
        this.fileKey = UUID.randomUUID().toString();
        this.srcFilePath = srcFilePath;
        File srcFile = new File(srcFilePath);
        this.fileLength = (int)srcFile.length();
        try {
            this.inputStream = new FileInputStream(srcFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    public String getFileKey() {
        return fileKey;
    }
    public String getSrcFilePath() {
        return srcFilePath;
    }
    public int getFileLength() {
        return fileLength;
    }
    public boolean isReadFinish() {
        return isReadFinish;
    }
    public byte[] readBytes() {
        try {
            if(this.inputStream == null) {
                return null;
            }
            byte[] buffer = new byte[1024 * 1024 * 5];
            this.inputStream.read(buffer);
            this.transferByteCount += buffer.length;
            if(this.transferByteCount >= this.fileLength) {
                this.isReadFinish = true;
                this.transferByteCount = this.fileLength;
            }
            return buffer;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
   
    public void closeInputStream() {
        if(this.inputStream != null) {
            try {
                this.inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

然后,在 RMI 服务接口方法实现类中构建一个线程安全的集合,用来存储管理各个大文件的传输过程,代码如下:

/**
* 下载文件状态监视器
*/
private Hashtable<String,RFileDownloadTransfer> downloadFileStatusMonitor = new Hashtable<String,RFileDownloadTransfer>();

2.2.2 CS 握接口设计

CS 握手接口名称为 startDownloadFile,主要功能就是传输交换文件基本信息,构建文件下载过程状态控制对象。其在接口实现类中的代码如下所示:

@Override
public Map<String, String> startDownloadFile(String srcFilePath) throws RemoteException {
    RFileDownloadTransfer fileTransfer = new RFileDownloadTransfer(srcFilePath);
    if(this.downloadFileStatusMonitor.containsKey(fileTransfer.getFileKey())) {
        this.downloadFileStatusMonitor.remove(fileTransfer.getFileKey());
    }
    this.downloadFileStatusMonitor.put(fileTransfer.getFileKey(), fileTransfer);
    Map<String,String> fileInfoList = new HashMap<String,String>();
    fileInfoList.put(“fileLength”, String.valueOf(fileTransfer.getFileLength()));
    fileInfoList.put(“fileKey”, fileTransfer.getFileKey());
    return fileInfoList;
}

2.2.3 文件内容下载更新接口设计

文件内容下载更新接口名称为 updateDownloadProgress,主要功能是接收客户端传输过来的文件内容 byte[]信息。其在接口实现类中的代码如下所示:

@Override
public byte[] updateDownloadProgress(String fileKey) throws RemoteException {
    if(this.downloadFileStatusMonitor.containsKey(fileKey)) {
        RFileDownloadTransfer fileTransfer = this.downloadFileStatusMonitor.get(fileKey);
        byte[] bytes = fileTransfer.readBytes();
        if(fileTransfer.isReadFinish()) {
            fileTransfer.closeInputStream();
            this.downloadFileStatusMonitor.remove(fileKey);
        }
        return bytes;
    }
    return null;
}

2.2.4 客户端设计

客户端的主要功能是创建磁盘文件,逐批次获取文件内容 byte[]信息,并将其写入输出流中,同时进行传输进度的提醒,并最终生成完整的文件。下面是笔者本人采用 swing 开发的测试代码,采用 JProgressBar 进行进度的实时提醒。

Map<String,String> fileInfoList = getFileManageService().startDownloadFile(remoteFilePath);
int fileLength = Integer.valueOf(fileInfoList.get(“fileLength”));
String fileKey = fileInfoList.get(“fileKey”);
int transferByteCount = 0;
                   
progressBar.setMinimum(0);
progressBar.setMaximum(100);
                   
OutputStream out = new FileOutputStream(localFilePath);
while(true) {
    if(transferByteCount >= fileLength) {
        break;
    }
                       
    byte[] bytes = getFileManageService().updateDownloadProgress(fileKey);
    if(bytes == null) {
        break;
    }
                       
    if(transferByteCount + bytes.length > fileLength) {
        // 如果之前已经传输的数据长度 + 本批数据长度 > 文件长度的话,说明这批数据是最后一批数据了;
        // 那么本批数据中将会有空字节,需要筛选出来。
        byte[] contents = new byte[fileLength – transferByteCount];
        for(int i=0;i<contents.length;i++) {
            contents[i] = bytes[i];
        }
        transferByteCount = fileLength;
        out.write(contents);
    } else {
        // 说明本批数据并非最后一批数据,文件还没有传输完。
        transferByteCount += bytes.length;
        out.write(bytes);
    }
                       
    double dblFinishPercent = (transferByteCount * 1.0 / fileLength) * 100;
    int finishPercent = (int)dblFinishPercent;
    if(finishPercent > 100) {
        finishPercent = 100;
    }
    progressBar.setValue(finishPercent);
}
                   
if(transferByteCount != fileLength) {
    LogInfoUtil.printLog(“ 不能完整地读取文件 ” + remoteFilePath);
} else {
    progressBar.setValue(100);
    out.flush();
    if(out != null) {
        try {
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

实例界面截图如下所示:

基于 RMI 服务传输大文件的完整解决方案

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-02/128710.htm

基于 RMI 服务传输大文件,分为上传和下载两种操作,需要注意的技术点主要有三方面,第一,RMI 服务中传输的数据必须是可序列化的。第二,在传输大文件的过程中应该有进度提醒机制,对于大文件传输来说,这点很重要,因为大文件的传输时间周期往往比较长,必须实时告知用户大文件的传输进度。第三,针对大文件的读取方式,如果采用一次性将大文件读取到 byte[]中是不现实的,因为这将受制于 JVM 的可用内存,会导致内存溢出的问题。

笔者实验的基于 RMI 服务传输大文件的解决方案,主要就是围绕以上三方面进行逐步解决的。下面将分别就上传大文件和下载大文件进行阐述。

1. 基于 RMI 服务上传大文件

1.1. 设计思路

上传大文件分为两个阶段,分别为“CS 握手阶段”和“文件内容上传更新阶段”。

CS 握手阶段,又可称之为客户端与服务端之间的基本信息交换阶段。客户端要确定待上传的本地文件和要上传到服务端的目标路径。读取本地文件,获取文件长度,将本地文件长度、本地文件路径和服务端目标路径等信息通过接口方法传递到服务端,然后由服务端生成具有唯一性的 FileKey 信息,并返回到客户端,此 FileKey 作为客户端与服务端之间数据传输通道的唯一标示。这些信息数据类型均为 Java 基本数据类型,因此都是可序列化的。此接口方法就称之为“握手接口”,通过 CS 握手,服务端能确定三件事:哪个文件要传输过来、这个文件的尺寸、这个文件将存放在哪里,而这三件刚好是完成文件上传的基础。

然后就是“文件内容上传更新阶段”。客户端打开文件后,每次读取一定量的文件内容,譬如每次读取(1024 * 1024 * 2)byte 的数据,并将此批数据通过“上传更新”接口方法传输到服务端,由服务端写入输出流中,同时检查文件内容是否已经传输完毕,如果已经传输完毕,则执行持久化 flush 操作在服务端生成文件;客户端每次传输一批数据后,就更新“已传输数据总量”标示值,并与文件总长度进行比对计算,从而得到文件上传进度,实时告知用户。综上所述,客户端循环读取本地文件内容并传输到服务端,直到文件内容读取上传完毕为止。

1.2. 功能设计

1.2.1 文件上传相关状态信息的管理

大文件上传的过程中,在服务端,最重要的是文件上传过程相关状态信息的精确管理,譬如,文件总长度、已上传字节总数、文件存储路径等等。而且要保证在整个上传过程中数据的实时更新和绝对不能丢失,并且在文件上传完毕后及时清除这些信息,以避免服务端累计过多失效的状态数据。

鉴于此,我们设计了一个类 RFileUploadTransfer 来实现上述功能。代码如下:

/**
 * Description: 文件上传过程相关状态信息封装类。<br>
 * Copyright: Copyright (c) 2016<br>
 * Company: 河南电力科学研究院智能电网所 <br>
 * @author shangbingbing 2016-01-01 编写
 * @version 1.0
 */
public class RFileUploadTransfer implements Serializable {
    private static final long serialVersionUID = 1L;
    private String fileKey;
    // 客户端文件路径
    private String srcFilePath;
    // 服务端上传目标文件路径
    private String destFilePath;
    // 文件尺寸
    private int fileLength = 0;
    // 已传输字节总数
    private int transferByteCount = 0;
    // 文件是否已经完整写入服务端磁盘中
    private boolean isSaveFile = false;
    private OutputStream out = null;
   
    public RFileUploadTransfer(String srcFilePath, int srcFileLength, String destFilePath) {
        this.fileKey = UUID.randomUUID().toString();
        this.srcFilePath = srcFilePath;
        this.fileLength = srcFileLength;
        this.destFilePath = destFilePath;
       
        File localFile = new File(this.destFilePath);
        if(localFile.getParentFile().exists() == false) {
            localFile.getParentFile().mkdirs();
        }
        try {
            this.out = new FileOutputStream(localFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
   
    public String getFileKey() {
        return fileKey;
    }
    public String getSrcFilePath() {
        return srcFilePath;
    }
    public String getDestFilePath() {
        return destFilePath;
    }
    public boolean isSaveFile() {
        return isSaveFile;
    }
   
    public void addContentBytes(byte[] bytes) {
        try {
            if(bytes == null || bytes.length == 0) {
                return;
            }
            if(this.transferByteCount + bytes.length > this.fileLength) {
                // 如果之前已经传输的数据长度 + 本批数据长度 > 文件长度的话,说明这批数据是最后一批数据了;
                // 由于本批数据中可能会存在有空字节,所以需要筛选出来。
                byte[] contents = new byte[this.fileLength – this.transferByteCount];
                for(int i=0;i<contents.length;i++) {
                    contents[i] = bytes[i];
                }
                this.transferByteCount = this.fileLength;
                this.out.write(contents);
            } else {
                // 说明本批数据并非最后一批数据,文件还没有传输完。
                this.transferByteCount += bytes.length;
                this.out.write(bytes);
            }
            if(this.transferByteCount >= this.fileLength) {
                this.out.flush();
                this.isSaveFile = true;
                if(this.out != null) {
                    try {
                        this.out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

然后,在 RMI 服务接口方法实现类中构建一个线程安全的集合,用来存储管理各个大文件的传输过程,代码如下:

/**
* 上传文件状态监视器
*/
private Hashtable<String,RFileUploadTransfer> uploadFileStatusMonitor = new Hashtable<String,RFileUploadTransfer>();

1.2.2 CS 握手接口设计

CS 握手接口名称为 startUploadFile,主要功能就是传输交换文件基本信息,构建文件上传过程状态控制对象。其在接口实现类中的代码如下所示:

@Override
public String startUploadFile(String localFilePath, int localFileLength, String remoteFilePath) throws RemoteException {
    RFileUploadTransfer fileTransfer = new RFileUploadTransfer(localFilePath,localFileLength,remoteFilePath);
    if(this.uploadFileStatusMonitor.containsKey(fileTransfer.getFileKey())) {
        this.uploadFileStatusMonitor.remove(fileTransfer.getFileKey());
    }
    this.uploadFileStatusMonitor.put(fileTransfer.getFileKey(), fileTransfer);
    return fileTransfer.getFileKey();
}

1.2.3 文件内容上传更新接口设计
文件内容上传更新接口名称为 updateUploadProgress,主要功能是接收客户端传输过来的文件内容 byte[]信息。其在接口实现类中的代码如下所示:

@Override
public boolean updateUploadProgress(String fileKey, byte[] contents) throws RemoteException {
    if(this.uploadFileStatusMonitor.containsKey(fileKey)) {
        RFileUploadTransfer fileTransfer = this.uploadFileStatusMonitor.get(fileKey);
        fileTransfer.addContentBytes(contents);
        if(fileTransfer.isSaveFile()) {
            this.uploadFileStatusMonitor.remove(fileKey);
        }
    }
    return true;
}

1.2.4 客户端设计

客户端的主要功能是打开本地文件,按批读取文件内容 byte[]信息,调用 RMI 接口方法进行传输,同时进行传输进度的提醒。下面是笔者本人采用 swing 开发的测试代码,采用 JProgressBar 进行进度的实时提醒。

progressBar.setMinimum(0);
progressBar.setMaximum(100);
InputStream is = null;
try {
    File srcFile = new File(localFilePath);
    int fileSize = (int)srcFile.length();
    String fileKey = getFileManageService().startUploadFile(localFilePath, fileSize, remoteFilePath);
                           
    byte[] buffer = new byte[1024 * 1024 * 2];
    int offset = 0;
    int numRead = 0;
    is = new FileInputStream(srcFile);
    while(-1 != (numRead=is.read(buffer))) {
        offset += numRead;
        getFileManageService().updateUploadProgress(fileKey, buffer);
        double finishPercent = (offset * 1.0 / fileSize) * 100;
        progressBar.setValue((int)finishPercent);
    }
    if(offset != fileSize) {
        throw new IOException(“ 不能完整地读取文件 ” + localFilePath);
    } else {
        progressBar.setValue(100);
    }
} catch (Exception ex) {
    ex.printStackTrace();
} finally {
    try {
        if(is != null) {
            is.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

实例界面截图如下所示:

基于 RMI 服务传输大文件的完整解决方案

更多详情见请继续阅读下一页的精彩内容:http://www.linuxidc.com/Linux/2016-02/128710p2.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-21发表,共计16318字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中