Android 上传文件至ftp 

注意:

1、该文章中的ftp上传文件需要配置Apache的 commons-net-3.6.jar 使用  

2、ftp的图片是无法在App上直接浏览的 可以通过配置 Nginx 来解决

public class FTPUtils {


    //ftp服务器地址
    private String hostname = "";
    //ftp服务器端口号默认为21
    private Integer port = 21;
    //ftp登录账号
    private String username = "";
    //ftp登录密码
    private String password = "";
    //超时时间
    public int timeOut = 2;
    //被动模式开关 如果不开被动模式 有防火墙 可能会上传失败, 但被动模式需要ftp支持
    public boolean enterLocalPassiveMode = false;

    private FTPClient ftpClient = null;

    private static FTPUtils mFTPUtils = null;


    private FTPUtils() {

    }

    public static FTPUtils getInstance() {
        if (mFTPUtils == null) {
            synchronized (FTPUtils.class) {
                if (mFTPUtils == null) {
                    mFTPUtils = new FTPUtils();
                }
            }
        }

        return mFTPUtils;
    }


    /**
     * 初始化配置  全局只需初始化一次
     * @param hostname  ftp服务器地址
     * @param port ftp服务器端口号默认为21
     * @param username ftp登录账号
     * @param password ftp登录密码
     */
    public void initFtpClient(String hostname, int port, String username, String password) {
        this.hostname = hostname;
        this.port = port;
        this.username = username;
        this.password = password;

        //初始化ftpclient对象
        ftpClient = new FTPClient();
        //设置超时时间以毫秒为单位使用时,从数据连接读。
        ftpClient.setDefaultTimeout(timeOut * 1000);
        ftpClient.setConnectTimeout(timeOut * 1000);
        ftpClient.setDataTimeout(timeOut * 1000);
        ftpClient.setControlEncoding("utf-8");

    }




    /**
     * 连接并登陆ftp
     * @return
     */
    private boolean connectFtp(){
        boolean flag = false;
        try {
            Log.e("FTP", "连接...FTP服务器...");
            ftpClient.connect(hostname, port); //连接ftp服务器
            //是否开启被动模式
            if (enterLocalPassiveMode) {
                ftpClient.setRemoteVerificationEnabled(false);
                ftpClient.enterLocalPassiveMode();
            }
            ftpClient.login(username, password); //登录ftp服务器
            int replyCode = ftpClient.getReplyCode(); //是否成功登录服务器
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                Log.e("--------->","连接...FTP服务器...失败: " + this.hostname + ":" + this.port+ "");
            }
            Log.e("FTP","连接...FTP服务器...成功:" + this.hostname + ":" + this.port);
        } catch (MalformedURLException e) {
            Log.e(e.getMessage(), e+"");
        } catch (IOException e) {
            Log.e(e.getMessage(), e+"");
        }
        return flag;
    }


    /**
     * 上传文件
     *
     * @param ftpSavePath     ftp服务保存地址  (不带文件名)
     * @param ftpSaveFileName 上传到ftp的文件名
     * @param originFile      待上传文件
     * @return
     */
    public boolean uploadFile(String ftpSavePath, String ftpSaveFileName, File originFile) {
        boolean flag = false;
        try {
            FileInputStream inputStream = new FileInputStream(originFile);
            flag = uploadFile(ftpSavePath, ftpSaveFileName, inputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.e("FTP", e.getMessage() + "  " + e);
        }
        return flag;
    }



    /**
     * 上传文件
     *
     * @param ftpSavePath     ftp服务保存地址  (不带文件名)
     * @param ftpSaveFileName 上传到ftp的文件名
     * @param originFileName  待上传文件的名称(绝对地址) *
     * @return
     */
    public boolean uploadFile(String ftpSavePath, String ftpSaveFileName, String originFileName) {
        boolean flag = false;

        try {
            FileInputStream inputStream = new FileInputStream(new File(originFileName));
            flag = uploadFile(ftpSavePath, ftpSaveFileName, inputStream);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.e("------------>", e.getMessage() + "  " + e);
        }
        return flag;
    }

    /**
     * 上传文件(直接读取输入流形式)
     *
     * @param ftpSavePath    ftp服务保存地址
     * @param ftpSaveFileName    上传到ftp的文件名
     * @param inputStream 输入文件流
     * @return
     */
    public boolean uploadFile(String ftpSavePath, String ftpSaveFileName, InputStream inputStream) {
        boolean flag = false;
        try {
            connectFtp();
            //第一次进来,将上传路径设置成相对路径
            if (ftpSavePath.startsWith("/")) {
                ftpSavePath = ftpSavePath.substring(1);
            }
            Log.e("FTP","上传文件的路径 :" + ftpSavePath);
            Log.e("FTP", "上传文件名 :" + ftpSaveFileName);
            //初始化FTP服务器
            connectFtp();
            L.e( "开始上传文件...");
            //设置文件类型,图片为二进制
            ftpClient.setFileType(ftpClient.BINARY_FILE_TYPE);
            //创建文件路径
            if (!CreateDirecroty(ftpSavePath)) {
                return flag;
            }
            flag = ftpClient.storeFile(new String(ftpSaveFileName.getBytes("GBK"), "iso-8859-1"), inputStream);
            inputStream.close();
            ftpClient.logout();
        } catch (Exception e) {
            Log.e(e.getMessage(), e+"");
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    Log.e(e.getMessage(), e+"");
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    Log.e(e.getMessage(), e+"");
                }
            }
            Log.e("FTP","上传文件结束...结果 :" + (flag ? "成功" : "失败 "));
        }
        return flag;
    }


    //改变目录路径
    public boolean changeWorkingDirectory(String directory) {
        boolean flag = true;
        try {
            flag = ftpClient.changeWorkingDirectory(directory);
            if (!flag) {
                L.e( "所在的目录 : " + ftpClient.printWorkingDirectory() + " 进入下一级 " + directory + " 目录失败");
            } else {
                Log.e("FTP","进入目录成功,当前所在目录 :" + ftpClient.printWorkingDirectory());
            }
        } catch (IOException ioe) {
            Log.e(ioe.getMessage(), ioe+"");
        }
        return flag;
    }

    //创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建
    public boolean CreateDirecroty(String remote) throws IOException {
        boolean success = true;
        String directory = remote + "/";
        // 如果远程目录不存在,则递归创建远程服务器目录
        if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(new String(directory))) {
            int start = 0;
            int end = 0;
            if (directory.startsWith("/")) {
                start = 1;
            } else {
                start = 0;
            }
            //从第一个"/"索引之后开始得到下一个"/"的索引
            end = directory.indexOf("/", start);
            while (true) {
                Log.e("FTP","所在的目录 :" + ftpClient.printWorkingDirectory());
                String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1");
                if (!existFile(subDirectory)) {
                    if (makeDirectory(subDirectory)) {
                        if (!changeWorkingDirectory(subDirectory)) {
                            return false;
                        }
                    } else {
                        return false;
                    }
                } else {
                    if (!changeWorkingDirectory(subDirectory)) {
                        return false;
                    }
                }

                start = end + 1;
                end = directory.indexOf("/", start);
                // 检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return success;
    }

    //判断ftp服务器文件是否存在
    public boolean existFile(String path) throws IOException {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        if (ftpFileArr.length > 0) {
            flag = true;
        }
        return flag;
    }

    //创建目录
    public boolean makeDirectory(String dir) {
        boolean flag = true;
        try {
            flag = ftpClient.makeDirectory(dir);
            if (!flag) {
                Log.e("FTP","所在的目录 : " + ftpClient.printWorkingDirectory() + " 创建下一级 " + dir + " 目录失败 ");
            } else {
                Log.e("FTP","所在的目录 : " + ftpClient.printWorkingDirectory() + " 创建下一级 " + dir + " 目录成功 ");
            }
        } catch (Exception e) {
            Log.e(e.getMessage(), e+"");
        }
        return flag;
    }

    /**
     * 下载文件 *
     *
     * @param pathname  FTP服务器文件目录 *
     * @param filename  文件名称 *
     * @param localpath 下载后的文件路径 *
     * @return
     */
    public boolean downloadFile(String pathname, String filename, String localpath) {
        boolean flag = false;
        OutputStream os = null;
        try {
            //第一次进来,将上传路径设置成相对路径
            if (pathname.startsWith("/")) {
                pathname = pathname.substring(1);
            }
            connectFtp();
            ftpClient.setFileType(ftpClient.BINARY_FILE_TYPE);
            //切换FTP目录
            changeWorkingDirectory(pathname);
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for (FTPFile file : ftpFiles) {
                if (filename.equalsIgnoreCase(file.getName())) {
                    File localFile = new File(localpath + "/" + file.getName());
                    os = new FileOutputStream(localFile);
                    ftpClient.retrieveFile(file.getName(), os);
                    os.close();
                }
            }
            ftpClient.logout();
            flag = true;
        } catch (Exception e) {
            Log.e(e.getMessage(), e+"");
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    Log.e(e.getMessage(), e+"");
                }
            }
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    Log.e(e.getMessage(), e+"");
                }
            }
        }
        return flag;
    }

    /**
     * 删除文件 *(未测试)
     *
     * @param pathname FTP服务器保存目录 *
     * @param filename 要删除的文件名称 *
     * @return
     */
    public boolean deleteFile(String pathname, String filename) {
        boolean flag = false;
        try {
            //第一次进来,将上传路径设置成相对路径
            if (pathname.startsWith("/")) {
                pathname = pathname.substring(1);
            }
            connectFtp();
            //切换FTP目录
            changeWorkingDirectory(pathname);
            ftpClient.dele(filename);
            ftpClient.logout();
            flag = true;
        } catch (Exception e) {
            Log.e("FTP","删除文件失败 ");
            Log.e("FTP",e.getMessage(), e+"");
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    Log.e(e.getMessage(), e+"");
                }
            }
        }
        return flag;
    }

    /**
     * 获取文件的输入流
     *
     * @param dir      ftp定义的存储路径 例如 /ftpFile/images
     * @param filename 上传的文件名
     * @return
     * @throws Exception
     *//*
    public InputStream getInputStream(String dir, String filename) {
        byte[] bytes = null;
        String path = dir + filename;
        InputStream in = null;
        try {
            connectFtp();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            // 转到指定下载目录
            if (path != null) {
                //验证是否有该文件夹,有就转到,没有创建后转到该目录下
                changeWorkingDirectory(path);// 转到指定目录下
            }
            // 不需要遍历,改为直接用文件名取
            String remoteAbsoluteFile = toFtpFilename(path);
            // 下载文件
            ftpClient.setBufferSize(1024 * 1024);
            ftpClient.setControlEncoding("UTF-8");
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(ftpClient.BINARY_FILE_TYPE);
            in = ftpClient.retrieveFileStream(remoteAbsoluteFile);
            *//*
             * bytes = input2byte(in); System.out.println("下载成功!" + bytes.length); //
			 * in.read(bytes); in.close();
			 *//*
        } catch (SocketException e) {
//            e.printStackTrace();
            Log.e(e.getMessage(), e+"");
        } catch (IOException e) {
//            e.printStackTrace();
            Log.e(e.getMessage(), e+"");
        } catch (Exception e) {
//            e.printStackTrace();
            Log.e(e.getMessage(), e+"");
        }
        return in;
    }*/

    /**
     * 文件转成 byte[]
     *
     * @param inStream
     * @return
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    public static byte[] input2byte(InputStream inStream) throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[inStream.available()];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] in2b = swapStream.toByteArray();
        swapStream.close();
        return in2b;
    }

    /**
     * 转化输出的编码
     */
    private static String toFtpFilename(String fileName) throws Exception {
        return new String(fileName.getBytes("UTF-8"), "ISO8859-1");
    }


}