11.4. 接收文件

使用文件传输API,从已登录的MQ服务器上接收一个文件,包括以下步骤:

以下代码演示了如何使用文件传输API,从已登录的MQ服务器上接收一个文件:

    public static void main(String[] args) throws Exception {
        //创建登陆器对象,在创建对象时指定要登录的服务器的IP地址,端口号,用户名和密码
        //注意:必须将“admin”作为用户名和并提供其密码,因为 AMQ 的文件传输功能目前
        //限制只能由“admin”用户使用。
        IMqLoginer loginer = new JaasLoginerImpl("localhost", 4888, "admin", "admin");
        loginer.login();
        //创建对象工厂,并创建文件接收器对象和文件传输服务管理对象。
        FileTransporterObjectFactory factory = new FileTransporterObjectFactory(loginer);
        IFileReceiver receiver = factory.createClientFileReceiver();
        IFileTransportManager transportManager = factory.createFileTransportManager();        
        
        //得到登录的服务器上接收到的文件列表。
        System.out.println("Received files list : ");
        int i = 0;
        Collection receivedFiles = transportManager.getAllReceivedFiles();
        Iterator ite = receivedFiles.iterator();
        FileTransportInfo firstFileInfo = null; 
        while (ite.hasNext()) {
            FileTransportInfo fileInfo = (FileTransportInfo)ite.next();
            System.out.println("File " + i + " : ");
            System.out.println("File Name : " + fileInfo.getFileName());
            System.out.println("File Size : " + fileInfo.getFileSize());
            System.out.println("File Remark : " + fileInfo.getRemark());
            System.out.println("File Sender User Name : " + fileInfo.getSenderUserName());
            System.out.println("File Source Router Name : " + fileInfo.getSrcRouterName());
            System.out.println("File UUID : " + fileInfo.getFileUuid());
            System.out.println();
            //在该示例程序中,我们始终将列表的第一个文件作为选择接收的文件。
            if (firstFileInfo == null) {
                firstFileInfo = fileInfo;
            }            
            i++;
        }
        
        //假如服务器上没有接收到的文件,退出程序。
        if (firstFileInfo == null) {
            System.exit(0);
        }
        
        //指定要接收的文件即将存放到本地机器的哪个目录。
        //假如这里的路径指定为某个具体文件的路径,表示将继续接收文件,并将接收到的内容
        //存放到该路径指定的文件中,继续接收时会读取跟该路径指定的文件相关联接收信息配
        //置文件,得到接收信息继续接收文件。接收信息配置文件的文件名为:该路径指定的文
        //件的文件名 + “.tfcfg”。假如没有找到该配置文件,继续接收将会出错。
        String receivePath = "D:\\";

        //继续接收时,将接收路径指定为要继续接收的文件的路径:
        //String continueReceivePath = "D:\\jdk-1_5_0_07-windows-i586-p.rar";

        //使用以上的参数创建接收信息对象。
        FileReceivingInfo info = new FileReceivingInfo(receivePath, firstFileInfo.getFileUuid());
        
        //向文件接收器中加入监听器,监听接收器的状态转换。
        receiver.addFileReceiverListener(new ClientFileReceiverListener());
        
        //启动一个新的线程,用于接收用户输入取消接收,因为主线程调用receive方法之后
        //将会处于阻塞状态。在新启动的线程中调用IFileReceiver的cancelCurrentReceiving方法
        //取消接收。
        CancelReceivingThread cancelThread = new CancelReceivingThread(receiver);
        cancelThread.start();
        
        //开始接收文件,并得到receive返回之后的接收结果,判断接收是否出现异常了。
        //还可以判断文件是否已经接收完毕。
        FileReceivingResult result = receiver.receive(info);
        if (result.getReceiveFileException() != null) {
            throw new Exception("Receive file exception.", result.getReceiveFileException());
        }        
        
        //登出服务器。
        loginer.logout();
    }

文件接收器的监听器代码:

 
    class ClientFileReceiverListener implements IFileReceiverListener {
        
        //打印文件接收进度等信息的线程。
        private PrintReceivingStateThread printThread;
        
        private ClientFileReceiverListener() {            
        }

        /**
         * 当接收器准备完毕,开始接收文件的时候会调用监听器的该方法。
         * 调用该方法之前,接收器已经处于STATE_RECEIVING状态。
         * @param receiver
         *               发生该状态变化的接收器。
         */
        public void onAfterReceivingStarted(IFileReceiver receiver) {
            //启动打印文件接收状态线程,在线程中调用IFileReceiver的getCurrentReceivingFileSize
            //getFileReceivedSize等方法显示文件接收进度等信息。
            printThread = new PrintReceivingStateThread(receiver);
            printThread.start();
            //进行日志记录等代码
            ...          
        }

        /**
         * 当接收器已经停止了接收文件,会调用监听器的该方法。
         * 调用该方法的时候,接收器已经处于STATE_IDLE状态。
         * @param receiver
         *               发生该状态变化的接收器。
         */
        public void onAfterReceivingStoped(IFileReceiver receiver) {
            //停止打印接收状态线程。
            synchronized (this.printThread.getPrintThreadSemaphore()) {
                this.printThread.getPrintThreadSemaphore().notifyAll();
            }
            //进行日志记录等代码
            ...  
        }

        /**
         * 当接收器准备停止接收文件,在停止之前会调用监听器的该方法。
         * 调用该方法的时候,接收器还不是处于STATE_IDLE状态。
         * @param receiver
         *               发生该状态变化的接收器。
         */
        public void onBeforeReceivingStoped(IFileReceiver receiver) {
            //可以在该方法中显示文件接收器停止接收之前,总共接收了文件的多少字节
            //接收进度等信息。或者进行日志记录等。
        }
        
    }