• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    1年前 (2017-08-14)  java |   抢沙发  15 
    文章评分 0 次,平均分 0.0

    最近使用apache上面的commons 2.0开发ftp使用过程中,因为涉及到大文件的长时间传输,在最后经常导致程序死掉。其中传文件的代码如下:

    /** 
     * 上传文件到服务器,新上传和断点续传 
     * @param remoteFile 远程文件名,在上传之前已经将服务器工作目录做了改变 
     * @param localFile 本地文件File句柄,绝对路径 
     * @param processStep 需要显示的处理进度步进值 
     * @param ftpClient FTPClient引用 
     * @return 
     * @throws IOException 
     */  
    public boolean uploadFile(String remoteFile,File localFile,FTPClient ftpClient,long remoteSize) throws IOException{  
        boolean status;  
        //显示进度的上传  
        long step = localFile.length() / 100;  
        long process = 0;  
        long localreadbytes = 0L;  
        RandomAccessFile raf = new RandomAccessFile(localFile,"r");  
        OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"),"iso-8859-1"));  
        //断点续传设置起始位置  
        if(remoteSize>0){  
            ftpClient.setRestartOffset(remoteSize);  
            process = remoteSize /step;  
            raf.seek(remoteSize);  
            localreadbytes = remoteSize;  
        }  
        byte[] bytes = new byte[1024];  
        int c;  
        //开始上传  
        while((c = raf.read(bytes))!= -1){  
            out.write(bytes,0,c);  
            localreadbytes+=c;  
            if(localreadbytes / step != process){  
                process = localreadbytes / step;  
    //          System.out.println("上传进度:" + process);  
                //TODO 添加汇报上传状态内容  
            }  
        }  
        logger.info("清空输出流");  
        out.flush();  
        logger.info("关闭文件读句柄");  
        raf.close();  
        logger.info("关闭输出流");  
        out.close();  
        logger.info("关闭输出流成功");  
        boolean status = ftpClient.completePendingCommand();  
        logger.info("从上传方法返回");  
        return status;  
    }  
    

    如果上传大的文件,比如说是500M文件,ftp传输大概需要两个小时左右的时候,ftpClient.completePendingCommand()方法就会死掉,我在网上也查了一些内容,说是打开的流必须关闭后ftp Server才会返回正确的状态吗。问题是我关闭了同样没有收到正确的状态码。

    如果换成appendFile(String remoteFile,InputStream in)这种方法就不会存在问题,

    问题在于completePendingCommand()方法始终不能返回,介绍一下我在调试过程中遇到的问题。
    1.FTP服务器有控制连接和数据连接,我的猜测是在进行数据传输的过程中,数据连接一直工作,但是控制连接可能就处于空闲状态,造成被服务器主动关闭,因此不能正常返回。
    2.在网上也看了一些网友的介绍,说在调用completePendingCommand()方法时必须关闭输入输出流,而调用这个方法主要就是为了拿到服务器端的226相应(File OK)。
    3.我的方法再调用completePendingCommand()方法时,输入输出流确实已经关闭,所以上诉的第2点不适合我的程序。
    4.另外我对程序进行更改,不调用completePendingCommand()方法,直接返回 后,发现在后续的程序中,如果发送命令(如PASV)到服务器端,收到的响应为226 File receive OK.而后续的基本上都正常了。

    综合以上分析我采用如下的方法来处理:
    在关闭输入输出流后发送NOOP命令激活控制连接,然后调用completePendingCommand()方法返回。
    现在我测试的结果是,即使数据传输3个小时,也不会造成程序假死。

    while((c = raf.read(bytes))!= -1){  
        out.write(bytes,0,c);  
        localreadbytes+=c;  
        if(localreadbytes / step != process){  
            process = localreadbytes / step;  
    //      System.out.println("上传进度:" + process);  
            //汇报上传状态,汇报进度函数,自己实现  
            reportUploadPercent((int)process);  
        }  
        out.flush();  
    }  
    raf.close();  
    out.close();  
    ftpClient.sendNoOp();  
    boolean result = ftpClient.completePendingCommand();  
     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/5528.html

    关于

    发表评论

    暂无评论

    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享