Java常用FTP文件操作说明 Apache.FTPClient,ftp4j,jftp

最近因工作需要,数据库中的数据需要从FTP服务中抽取数据文件然后校检再抽取到数据中。因为第一步需要从FTP服务中抽取数据文件。第二步采用JDBC批量数据更新。

1。采用Apache.FTPClient:

/**
 * Apache.FTPClient FTP操作共公类
 *
 * @author 张明学
 *
 */
public class FTPCommon {

    private FTPClient ftpClient;

    private FTPModel ftpModel;

    public FTPCommon(FTPModel ftp) {
        super();
        // 从配置文件中读取初始化信息
        this.ftpClient = new FTPClient();
        this.ftpModel = ftp;
    }

    /**
     * 连接并登录FTP服务器
     *
     */
    public boolean ftpLogin() {
        boolean isLogin = false;
        FTPClientConfig ftpClientConfig = new FTPClientConfig(
                FTPClientConfig.SYST_NT);
        ftpClientConfig.setServerTimeZoneId(TimeZone.getDefault().getID());
        this.ftpClient.setControlEncoding("GBK");
        this.ftpClient.configure(ftpClientConfig);
        try {
            if (this.ftpModel.getPort() > 0) {
                this.ftpClient.connect(ftpModel.getUrl(), ftpModel.getPort());
            } else {
                this.ftpClient.connect(ftpModel.getUrl());
            }
            // FTP服务器连接回答
            int reply = this.ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                this.ftpClient.disconnect();
                return isLogin;
            }
            this.ftpClient.login(this.ftpModel.getUsername(), this.ftpModel
                    .getPassword());
            this.ftpClient.changeWorkingDirectory(this.ftpModel.getRemoteDir());
            this.ftpClient.setFileType(FTPClient.FILE_STRUCTURE);
            LogUtil.infoOutPut("成功登陆FTP服务器:" + this.ftpModel.getUrl() + " 端口号:"
                    + this.getFtpModel().getPort() + " 目录:"
                    + this.ftpModel.getRemoteDir());
            isLogin = true;
        } catch (SocketException e) {
            e.printStackTrace();
            LogUtil.logPrint("连接FTP服务失败!", Constants.LOG_EXCEPTION);
            LogUtil.logPrint(e.getMessage(), Constants.LOG_EXCEPTION);
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.logPrint("登录FTP服务失败!", Constants.LOG_EXCEPTION);
            LogUtil.logPrint(e.getMessage(), Constants.LOG_EXCEPTION);
        }
        System.out.println(this.ftpClient.getBufferSize());
        this.ftpClient.setBufferSize(1024 * 2);
        this.ftpClient.setDataTimeout(2000);
        return isLogin;
    }

    /**
     * 退出并关闭FTP连接
     *
     */
    public void close() {
        if (null != this.ftpClient && this.ftpClient.isConnected()) {
            try {
                boolean reuslt = this.ftpClient.logout();// 退出FTP服务器
                if (reuslt) {
                    LogUtil.info("退出并关闭FTP服务器的连接");
                }
            } catch (IOException e) {
                e.printStackTrace();
                LogUtil.exception("退出FTP服务器异常!");
                LogUtil.exception(e.getMessage());
            } finally {
                try {
                    this.ftpClient.disconnect();// 关闭FTP服务器的连接
                } catch (IOException e) {
                    e.printStackTrace();
                    LogUtil.exception("关闭FTP服务器的连接异常!");
                    LogUtil.exception(e.getMessage());
                }
            }
        }
    }

    /**
     * 检查FTP服务器是否关闭 ,如果关闭接则连接登录FTP
     *
     * @return
     */
    public boolean isOpenFTPConnection() {
        boolean isOpen = false;
        if (null == this.ftpClient) {
            return false;
        }
        try {
            // 没有连接
            if (!this.ftpClient.isConnected()) {
                isOpen = this.ftpLogin();
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.exception("FTP服务器连接登录异常!");
            LogUtil.exception(e.getMessage());
            isOpen = false;
        }
        return isOpen;
    }

    /**
     * 设置传输文件的类型[文本文件或者二进制文件]
     *
     * @param fileType--FTPClient.BINARY_FILE_TYPE,FTPClient.ASCII_FILE_TYPE
     */
    public void setFileType(int fileType) {
        try {
            this.ftpClient.setFileType(fileType);
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.exception("设置传输文件的类型异常!");
            LogUtil.exception(e.getMessage());
        }
    }

    /**
     * 下载文件
     *
     * @param localFilePath
     *            本地文件名及路径
     * @param remoteFileName
     *            远程文件名称
     * @return
     */
    public boolean downloadFile(String localFilePath, String remoteFileName) {
        BufferedOutputStream outStream = null;
        boolean success = false;
        try {
            outStream = new BufferedOutputStream(new FileOutputStream(
                    localFilePath));
            success = this.ftpClient.retrieveFile(remoteFileName, outStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outStream != null) {
                try {
                    outStream.flush();
                    outStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }

    /**
     * 下载文件
     *
     * @param localFilePath
     *            本地文件
     * @param remoteFileName
     *            远程文件名称
     * @return
     */
    public boolean downloadFile(File localFile, String remoteFileName) {
        BufferedOutputStream outStream = null;
        FileOutputStream outStr = null;
        boolean success = false;
        try {
            outStr = new FileOutputStream(localFile);
            outStream = new BufferedOutputStream(outStr);
            success = this.ftpClient.retrieveFile(remoteFileName, outStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != outStream) {
                    try {
                        outStream.flush();
                        outStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (null != outStr) {
                    try {
                        outStr.flush();
                        outStr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            }
        }
        return success;
    }

    /**
     * 上传文件
     *
     * @param localFilePath
     *            本地文件路径及名称
     * @param remoteFileName
     *            FTP 服务器文件名称
     * @return
     */
    public boolean uploadFile(String localFilePath, String remoteFileName) {
        BufferedInputStream inStream = null;
        boolean success = false;
        try {
            inStream = new BufferedInputStream(new FileInputStream(
                    localFilePath));
            success = this.ftpClient.storeFile(remoteFileName, inStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }

    /**
     * 上传文件
     *
     * @param localFilePath
     *            本地文件
     * @param remoteFileName
     *            FTP 服务器文件名称
     * @return
     */
    public boolean uploadFile(File localFile, String remoteFileName) {
        BufferedInputStream inStream = null;
        boolean success = false;
        try {
            inStream = new BufferedInputStream(new FileInputStream(localFile));
            success = this.ftpClient.storeFile(remoteFileName, inStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }

    /**
     * 变更工作目录
     *
     * @param remoteDir--目录路径
     */
    public void changeDir(String remoteDir) {
        try {
            this.ftpClient.changeWorkingDirectory(remoteDir);
            LogUtil.info("变更工作目录为:" + remoteDir);
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.exception("变更工作目录为:" + remoteDir + "时出错!");
            LogUtil.exception(e.getMessage());
        }

    }

    /**
     * 变更工作目录
     *
     * @param remoteDir--目录路径
     */
    public void changeDir(String[] remoteDirs) {
        String dir = "";
        try {
            for (int i = 0; i < remoteDirs.length; i++) {
                this.ftpClient.changeWorkingDirectory(remoteDirs[i]);
                dir = dir + remoteDirs[i] + "/";
            }
            LogUtil.info("变更工作目录为:" + dir);
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.exception("变更工作目录为:" + dir + "时出错!");
            LogUtil.exception(e.getMessage());
        }

    }

    /**
     * 返回上级目录
     *
     */
    public void toParentDir(String[] remoteDirs) {
        try {
            for (int i = 0; i < remoteDirs.length; i++) {
                this.ftpClient.changeToParentDirectory();
            }
            LogUtil.info("返回上级目录");
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.exception("返回上级目录时出错!");
            LogUtil.exception(e.getMessage());
        }
    }

    /**
     * 返回上级目录
     *
     */
    public void toParentDir() {
        try {
            this.ftpClient.changeToParentDirectory();
            LogUtil.info("返回上级目录");
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.exception("返回上级目录时出错!");
            LogUtil.exception(e.getMessage());
        }
    }

    /**
     * 获得FTP 服务器下所有的文件名列表
     *
     * @param regex
     * @return
     */
    public String[] getListFiels() {
        String files[] = null;
        try {
            files = this.ftpClient.listNames();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return files;
    }

    public FTPClient getFtpClient() {
        return ftpClient;
    }

    public FTPModel getFtpModel() {
        return ftpModel;
    }

    public void setFtpModel(FTPModel ftpModel) {
        this.ftpModel = ftpModel;
    }

}


2。采用FTP4J:

Java代码

/**
 * ftp4j FTP操作共公类
 *
 * @author 张明学
 *
 */
public class FTP4JCommon {
    FTPClient ftpClient = null;

    FTPModel ftpModel = null;

    public FTP4JCommon() {

    }

    public FTP4JCommon(FTPModel ftpModel) {
        this.ftpModel = ftpModel;
    }

    /**
     * 连接并登录FTP服务器
     *
     */
    public boolean ftpLogin() {
        ftpClient = new FTPClient();
        try {
            // 建立连接
            ftpClient.connect(ftpModel.getUrl());
            ftpClient.setType(FTPClient.TYPE_AUTO);
            ftpClient.setCharset("GBK");
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.infoOutPut("与FTP服务器建立连接失败!");
            LogUtil.exception(e.getMessage());
        }
        try {
            ftpClient.login(ftpModel.getUsername(), ftpModel.getPassword());
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.infoOutPut("登录FTP服务器失败!");
            LogUtil.exception(e.getMessage());
        }
        return true;
    }

    /**
     * 退出并关闭FTP连接
     *
     */
    public void close() {
        if (null != ftpClient) {
            try {
                ftpClient.disconnect(true);
            } catch (Exception e) {
                e.printStackTrace();
                LogUtil.infoOutPut("安全退出FTP服务时异常!");
                LogUtil.exception(e.getMessage());
            }
        }
    }

    /**
     * 下载文件
     *
     * @param localFilePath
     *            本地文件名及路径
     * @param remoteFileName
     *            远程文件名称
     * @return
     * @throws Exception
     */
    public void downloadFile(String localFilePath, String remoteFileName)
            throws Exception {
        File localFile = new File(localFilePath);
        try {
            ftpClient.download(remoteFileName, localFile);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.infoOutPut("下载" + remoteFileName + "时出现异常!");
            LogUtil.exception(e.getMessage());
            throw e;
        }
    }

    /**
     * 下载文件
     *
     * @param localFilePath
     *            本地文件名及路径
     * @param remoteFileName
     *            远程文件名称
     * @return
     * @throws Exception
     */
    public void downloadFile(File localFile, String remoteFileName)
            throws Exception {
        try {
            ftpClient.download(remoteFileName, localFile);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.infoOutPut("下载" + remoteFileName + "时出现异常!");
            LogUtil.exception(e.getMessage());
            throw e;
        }
    }

    /**
     * 获得FTP 服务器下所有的文件名列表
     *
     * @param regex
     * @return
     */
    public String[] getListFiels() {
        String fileNames[] = null;
        try {
            fileNames = this.ftpClient.listNames();
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.infoOutPut("获取文件名列表时出现异常!");
            LogUtil.exception(e.getMessage());
        }
        return fileNames;
    }

    public FTPModel getFtpModel() {
        return ftpModel;
    }

    public void setFtpModel(FTPModel ftpModel) {
        this.ftpModel = ftpModel;
    }

    public FTPClient getFtpClient() {
        return ftpClient;
    }

}


  1. /** 
  2.  * ftp4j FTP操作共公类 
  3.  *  
  4.  * @author 张明学 
  5.  *  
  6.  */  
  7. public class FTP4JCommon {  
  8.     FTPClient ftpClient = null;  
  9.   
  10.     FTPModel ftpModel = null;  
  11.   
  12.     public FTP4JCommon() {  
  13.   
  14.     }  
  15.   
  16.     public FTP4JCommon(FTPModel ftpModel) {  
  17.         this.ftpModel = ftpModel;  
  18.     }  
  19.   
  20.     /** 
  21.      * 连接并登录FTP服务器 
  22.      *  
  23.      */  
  24.     public boolean ftpLogin() {  
  25.         ftpClient = new FTPClient();  
  26.         try {  
  27.             // 建立连接  
  28.             ftpClient.connect(ftpModel.getUrl());  
  29.             ftpClient.setType(FTPClient.TYPE_AUTO);  
  30.             ftpClient.setCharset("GBK");  
  31.         } catch (Exception e) {  
  32.             e.printStackTrace();  
  33.             LogUtil.infoOutPut("与FTP服务器建立连接失败!");  
  34.             LogUtil.exception(e.getMessage());  
  35.         }  
  36.         try {  
  37.             ftpClient.login(ftpModel.getUsername(), ftpModel.getPassword());  
  38.         } catch (Exception e) {  
  39.             e.printStackTrace();  
  40.             LogUtil.infoOutPut("登录FTP服务器失败!");  
  41.             LogUtil.exception(e.getMessage());  
  42.         }  
  43.         return true;  
  44.     }  
  45.   
  46.     /** 
  47.      * 退出并关闭FTP连接 
  48.      *  
  49.      */  
  50.     public void close() {  
  51.         if (null != ftpClient) {  
  52.             try {  
  53.                 ftpClient.disconnect(true);  
  54.             } catch (Exception e) {  
  55.                 e.printStackTrace();  
  56.                 LogUtil.infoOutPut("安全退出FTP服务时异常!");  
  57.                 LogUtil.exception(e.getMessage());  
  58.             }  
  59.         }  
  60.     }  
  61.   
  62.     /** 
  63.      * 下载文件 
  64.      *  
  65.      * @param localFilePath 
  66.      *            本地文件名及路径 
  67.      * @param remoteFileName 
  68.      *            远程文件名称 
  69.      * @return 
  70.      * @throws Exception 
  71.      */  
  72.     public void downloadFile(String localFilePath, String remoteFileName)  
  73.             throws Exception {  
  74.         File localFile = new File(localFilePath);  
  75.         try {  
  76.             ftpClient.download(remoteFileName, localFile);  
  77.         } catch (Exception e) {  
  78.             e.printStackTrace();  
  79.             LogUtil.infoOutPut("下载" + remoteFileName + "时出现异常!");  
  80.             LogUtil.exception(e.getMessage());  
  81.             throw e;  
  82.         }  
  83.     }  
  84.   
  85.     /** 
  86.      * 下载文件 
  87.      *  
  88.      * @param localFilePath 
  89.      *            本地文件名及路径 
  90.      * @param remoteFileName 
  91.      *            远程文件名称 
  92.      * @return 
  93.      * @throws Exception 
  94.      */  
  95.     public void downloadFile(File localFile, String remoteFileName)  
  96.             throws Exception {  
  97.         try {  
  98.             ftpClient.download(remoteFileName, localFile);  
  99.         } catch (Exception e) {  
  100.             e.printStackTrace();  
  101.             LogUtil.infoOutPut("下载" + remoteFileName + "时出现异常!");  
  102.             LogUtil.exception(e.getMessage());  
  103.             throw e;  
  104.         }  
  105.     }  
  106.   
  107.     /** 
  108.      * 获得FTP 服务器下所有的文件名列表 
  109.      *  
  110.      * @param regex 
  111.      * @return 
  112.      */  
  113.     public String[] getListFiels() {  
  114.         String fileNames[] = null;  
  115.         try {  
  116.             fileNames = this.ftpClient.listNames();  
  117.         } catch (Exception e) {  
  118.             e.printStackTrace();  
  119.             LogUtil.infoOutPut("获取文件名列表时出现异常!");  
  120.             LogUtil.exception(e.getMessage());  
  121.         }  
  122.         return fileNames;  
  123.     }  
  124.   
  125.     public FTPModel getFtpModel() {  
  126.         return ftpModel;  
  127.     }  
  128.   
  129.     public void setFtpModel(FTPModel ftpModel) {  
  130.         this.ftpModel = ftpModel;  
  131.     }  
  132.   
  133.     public FTPClient getFtpClient() {  
  134.         return ftpClient;  
  135.     }  
  136.   
  137. }  

 3。采用:jftp下载

Java代码
  1. /** 
  2.  * FTP实体对象 
  3.  *  
  4.  * @author 张明学 
  5.  *  
  6.  */  
  7. public class FTPModel {  
  8.   
  9.     private String ftpId;  
  10.   
  11.     private String username;  
  12.   
  13.     private String password;  
  14.   
  15.     private String url;  
  16.   
  17.     private int port;  
  18.   
  19.     private String remoteDir;  
  20.   
  21.     public FTPModel() {  
  22.   
  23.     }  
  24.   
  25.     public FTPModel(String username, String password, String url, int port,  
  26.             String remoteDir) {  
  27.         this.username = username;  
  28.         this.password = password;  
  29.         this.url = url;  
  30.         this.port = port;  
  31.         this.remoteDir = remoteDir;  
  32.     }  
  33. }  

/**
 * jftp FTP下载操作
 *
 * @author
 *
 */
public class JFTPDownloadCommon implements ConnectionListener {

    private boolean isThere = false;

    public static long time = 0;

    private FTPModel ftpModel = null;

    private ConnectionHandler handler = new ConnectionHandler();

    private FtpConnection ftpcon = null;

    public JFTPDownloadCommon(FTPModel ftpModel) {
        this.ftpModel = ftpModel;
        // 登录FTP
        this.ftpLogin();
    }

    /**
     * 连接并登录FTP服务器
     *
     */
    public boolean ftpLogin() {
        ftpcon = new FtpConnection(this.ftpModel.getUrl());
        ftpcon.addConnectionListener(this);
        ftpcon.setConnectionHandler(handler);
        // 登录
        ftpcon.login(ftpModel.getUsername(), ftpModel.getPassword());
        while (!isThere) {
            try {
                Thread.sleep(10);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        LogUtil.infoOutPut("是否登录成功:" + isThere);
        return isThere;
    }

    /**
     * 关闭与FTP服务器的连接
     *
     */
    public void close() {
        ftpcon.disconnect();
        LogUtil.infoOutPut("关闭与FTP的连接");
    }

    /**
     * 获得FTP 服务器下所有的文件名列表
     *
     * @param regex
     * @return
     */
    public String[] getListFiels() {
        ftpcon.exists("");
        Vector fileNameVector = ftpcon.currentFiles;
        String[] fileNames = new String[fileNameVector.size()];
        int i = 0;
        for (Iterator iter = fileNameVector.iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            fileNames[i] = name;
            i++;
        }
        return fileNames;
    }

    /**
     * 将FTP服务器上的file下载为bype型数据
     *
     * @param remoteFileName
     *            文件名
     * @return
     */
    public byte[] downloadToBinary(String remoteFileName) {
        Settings.bufferSize = 16384;
        long current = System.currentTimeMillis();
        byte[] bytes = null;
        try {
            InputStream is = ftpcon.getDownloadInputStream(remoteFileName);
            ByteArrayOutputStream bais = new ByteArrayOutputStream();
            int bit = 0;
            while ((bit = is.read()) != -1) {
                bais.write(bit);
            }
            bytes = bais.toByteArray();
        } catch (Exception e) {
        }
        time = (System.currentTimeMillis() - current);
        System.out.println("下载花费时间:" + time + "ms.");
        return bytes;
    }

    /**
     * 下载FTP服务器文件
     *
     * @param remoteFileName
     *            FTP服务器文件名
     * @param localFile
     *            本地文件名
     * @return
     * @throws Exception
     */
    public void downloadToBinary(String remoteFileName, File localFile)
            throws Exception {
        Settings.bufferSize = 16384;
        byte[] bytes = null;
        InputStream is = ftpcon.getDownloadInputStream(remoteFileName);
        ByteArrayOutputStream bais = new ByteArrayOutputStream();
        int bit = 0;
        while ((bit = is.read()) != -1) {
            bais.write(bit);
        }
        bytes = bais.toByteArray();
        CopyByteDataToLoacal(localFile, bytes);

    }

    /**
     * 将二进制文件下载到本地
     *
     * @param localFile
     *            目标文件名
     * @param fileDatas
     *            文件数据
     * @throws IOException
     */
    public void CopyByteDataToLoacal(File localFile, byte[] fileDatas)
            throws IOException {
        FileOutputStream fileOutStream = null;
        BufferedOutputStream bufferOutStream = null;
        try {
            if (localFile.exists()) {
                localFile.delete();
            }
            fileOutStream = new FileOutputStream(localFile);
            bufferOutStream = new BufferedOutputStream(fileOutStream);
            bufferOutStream.write(fileDatas);
        } catch (FileNotFoundException e) {
            LogUtil.exception(e.getMessage());
            throw e;
        } catch (IOException e) {
            LogUtil.exception(e.getMessage());
            throw e;
        } finally {
            try {
                if (null != bufferOutStream) {
                    bufferOutStream.flush();
                    bufferOutStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (null != fileOutStream) {
                    try {
                        fileOutStream.flush();
                        fileOutStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void connectionFailed(BasicConnection arg0, String arg1) {
        LogUtil.infoOutPut("与FTP服务器连接失败!");
    }

    public void connectionInitialized(BasicConnection arg0) {
        isThere = true;
    }

    public void updateRemoteDirectory(BasicConnection arg0) {
    }

    public void updateProgress(String arg0, String arg1, long arg2) {
    }

    public void actionFinished(BasicConnection arg0) {
    }

上面都用到了一个ftpModel如下(get,set方法省了):

/**
 * FTP实体对象
 *
 * @author 张明学
 *
 */
public class FTPModel {

    private String ftpId;

    private String username;

    private String password;

    private String url;

    private int port;

    private String remoteDir;

    public FTPModel() {

    }

    public FTPModel(String username, String password, String url, int port,
            String remoteDir) {
        this.username = username;
        this.password = password;
        this.url = url;
        this.port = port;
        this.remoteDir = remoteDir;
    }
}


上述仅仅列出了一点常用的操作,更多的操作需要参看它的们API文件。

 

还有,我采用的Serv-U作为FTP服务器,按装之后新建用户不法登录。后来找到了原因是:要把IIS服务中的FTP服务关掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值