Android开发-使用FTP协议和HTTP协议进行文件下载和上传

FTP 是File Transfer Protocol(文件传输协议)的英文简称,从这个名字也能看出来,这个协议是为了文件传输而生的。

使用前需要下载一个commons-net-3.3.jar

直接看上传代码

/** 
     * 向FTP服务器上传文件 
     *  
     * @param url 
     *            FTP服务器hostname 就是ip
     * @param port 21
     *            端口默认80 
     * @param username 
     *            用户名 
     * @param password 
     *            密码 
     * @param path 
     *            FTP服务器保存目录
     * @param filename
     *            文件名称 上传到FTP服务器上的文件名,是自己定义的名字 
     * @param input 
     *            文件输入流 
     * @return 
     */  
    public static boolean upload(String url, int port, String username,  
            String password, String path, String filename, InputStream input) {  
        
        boolean success = false;  
        FTPClient ftp = new FTPClient();  
        
        try {  
            ftp.setDataTimeout(2000);//设置连接超时时间  
            ftp.connect(url, port); 
            // 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器  
            ftp.login(username, password); 
            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {  
                ftp.disconnect();  //未连接到FTP,用户名或密码错误
                return success;  
            }  
            
            boolean isExist =  createDirecroty(path,ftp) ;  
            if(!isExist){  
                return success;  
            }  
            
            //获取服务器当前目录指定文件信息
            FTPFile[] files = ftp.listFiles(filename);
            if(files.length > 1){
                ftp.deleteFile(filename);
            }
              
            ftp.setControlEncoding("UTF-8");
            ftp.setBufferSize(1024);  
            ftp.enterLocalPassiveMode();    
            ftp.setFileType(FTP.BINARY_FILE_TYPE);  
            //处理中文名称的文件名,如果不加这一句的话,中文命名的文件是不能上传的  
            filename = new String(filename.getBytes("GBK"), "iso-8859-1") ;  
            ftp.storeFile(filename, input);  
  
            input.close();  
            ftp.logout(); 
            success = true;  
        } catch (IOException e) {
            e.printStackTrace();  
        } finally {  
            if (ftp.isConnected()) {  
                try {  
                    ftp.disconnect();  
                } catch (IOException ioe) {  
                }  
            }  
        }  
        return success;  

    }  

 /**
     * 递归创建远程服务器目录
     * 
     * @param remote
     *            远程服务器文件绝对路径
     * @return 目录创建是否成功
     * @throws IOException
     */
    public static boolean createDirecroty(String remote,FTPClient ftp) throws IOException {
        
        String totalPath = "";
        boolean success = true;
        String[] path = remote.split("/");
        for(int i=0; i<path.length; i++){            
            String father = path[i];
            if(father == null || "".equals(father)){
                success = false;
                break;
            }
            totalPath = totalPath + "/"+father;
            try {
                boolean isExit = ftp.changeWorkingDirectory(totalPath);
                if(!isExit){
                    boolean make = ftp.makeDirectory(totalPath);
                    if(!make){
                        success = false;
                        break;
                    }
                    //工作路径切换到此
                    boolean change = ftp.changeWorkingDirectory(totalPath);
                    if(!change){
                        success = false;
                        break;
                    }
                }
            } catch (IOException e) {
                success = false;
                break;
            }
        }  
        return success;

    }

流程其实很简单的,就是先连接FTP服务器(这里要求你的服务器支持FTP协议),再登陆,然后再创建相关目录,记住目录要一级一级创建,然后就是通过ftp上传了。这里其实看不到上传进度,就下来看另外一个方法

public static boolean upload(String url, int port, String username,  
            String password, String remotePath, File localFile) {  
        
        boolean success = false;  
        RandomAccessFile raf = null;
        OutputStream output = null;
        FTPClient ftp = new FTPClient();  
        
        try {  
            ftp.connect(url, port); 
            // 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器  
            ftp.login(username, password); 
            int reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {  
                ftp.disconnect();  //未连接到FTP,用户名或密码错误
                return success;  
            }  
            
            boolean isExist =  createDirecroty(remotePath,ftp) ;  
            if(!isExist){  
                return success;  
            }  
            
            //获取当前目录指定文件信息
            FTPFile[] files = ftp.listFiles(localFile.getName());
            if(files.length > 1){
                ftp.deleteFile(localFile.getName());
            }
              
            raf = new RandomAccessFile(localFile, "r");  
            long serverSize = 0;
            /* enterLocalPassiveMode 
             * 每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据。
             * 为什么要这样做呢,因为ftp server可能每次开启不同的端口来传输数据,
             * 但是在linux上或者其他服务器上面,由于安全限制,可能某些端口没有开启,
             * 所以就出现阻塞
             * */
            ftp.enterLocalPassiveMode();  
            ftp.setFileType(FTP.BINARY_FILE_TYPE);//设置二进制传输,还支持传输ACSII数据  
            ftp.setRestartOffset(serverSize);  
            raf.seek(serverSize);  
            
            // 进度  
            long localSize = localFile.length(); // 本地文件的长度 
            long step = localSize / 100;  
            long process = 0;  
            long currentSize = 0; 
            String filename = localFile.getName();
            filename = new String(filename.getBytes("GBK"), "iso-8859-1") ;  
            output = ftp.appendFileStream(filename);  
            byte[] b = new byte[1024];  
            int length = 0;  
            while ((length = raf.read(b)) != -1) {  
                output.write(b, 0, length);  
                currentSize = currentSize + length;  
                if (currentSize / step != process) {  
                    process = currentSize / step;  
                    Log.e(TAG, "上传进度:" + process);
                }  
            }  
             
            if (ftp.completePendingCommand()) {
                success = true; 
                Log.e(TAG, "文件上传成功");
            } 
  
        } catch (IOException e) {
            e.printStackTrace();  
        } finally {  
            
            try {
                output.flush();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }  
            
            try {
                raf.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            } 
            
            try {
                ftp.logout();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            if (ftp.isConnected()) {  
                try {  
                    ftp.disconnect();  
                } catch (IOException ioe) {  
                }  
            }  
        }  
        return success;  

    }

这里就是通过appendFileStream方法获取输出流来进行进度获取。

还可以通过ftp.setRestartOffset(serverSize);  raf.seek(serverSize);  来进行断点上传

上传结束,再来看下载

public static boolean downloadFile(String url, int port, String username,  
            String password, String localPath, String serverPath){  
        
        boolean success = false;  
        FTPClient ftpClient = new FTPClient();
 
        try {
            ftpClient.setControlEncoding("GBK"); 
            ftpClient.connect(url, port);
            ftpClient.login(username, password);
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {  
                ftpClient.disconnect();  //未连接到FTP,用户名或密码错误
                return false;    
            }
            
            // 先判断服务器文件是否存在  
            FTPFile[] files = ftpClient.listFiles(serverPath);  
            if (files.length == 0) {  
                Log.e(TAG,"服务器文件不存在 serverPath="+serverPath);  
                return false;  
            }  
            
            localPath = localPath + files[0].getName();  
            long serverSize = files[0].getSize(); // 获取远程文件的长度  
            File localFile = new File(localPath);  
            long localSize = 0;  
            if (localFile.exists()) {  
                localFile.delete(); 
            }  
            // 进度  
            long step = serverSize / 100;  
            long process = 0;  
            long currentSize = 0;  
            // 开始准备下载文件  
            ftpClient.enterLocalActiveMode();  
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);  
            OutputStream out = new FileOutputStream(localFile, true);  
            ftpClient.setRestartOffset(localSize); //设置从哪里开始下,就是断点下载 
            InputStream input = ftpClient.retrieveFileStream(serverPath);  
            byte[] b = new byte[1024];  
            int length = 0;  
            while ((length = input.read(b)) != -1) {  
                out.write(b, 0, length);  
                currentSize = currentSize + length;  
                if (currentSize / step != process) {  
                    process = currentSize / step;  
                    Log.e(TAG,"下载进度:" + process);   
                }  
            }  
            out.flush();  
            out.close();  
            input.close();  
            // 此方法是来确保流处理完毕,如果没有此方法,可能会造成现程序死掉  
            if (ftpClient.completePendingCommand()) {  
                Log.e(TAG,"文件下载成功");  
                success = true;
            } 
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return success;

    }

这里就是通过retrieveFileStream获取输入流进行下载。

 

再看看使用HTTP进行文件上传

    /**
     * 通过拼接的方式构造请求内容,实现参数传输以及文件传输
     * 
     * @param url http://192.168.1.19:8080/web/servlet/UploadServlet
     * @param params text content
     * @param files pictures
     * @return String result of Service response
     * @throws IOException
     */
    public static String post(String url, Map<String, String> params, Map<String, File> files)
            throws IOException {
        String BOUNDARY = java.util.UUID.randomUUID().toString();
        String PREFIX = "--";
        String LINEND = "\r\n";
        String MULTIPART_FROM_DATA = "multipart/form-data";
        String CHARSET = "UTF-8";

        URL uri = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
        conn.setReadTimeout(10 * 1000); 
        conn.setDoInput(true);// 允许输入
        conn.setDoOutput(true);// 允许输出
        conn.setUseCaches(false); // 不允许使用缓存
        conn.setRequestMethod("POST");
        conn.setRequestProperty("connection", "keep-alive");
        conn.setRequestProperty("Charsert", "UTF-8");
        conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);
        conn.setChunkedStreamingMode(1024);

        // 首先组拼文本类型的参数
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            sb.append(PREFIX);
            sb.append(BOUNDARY);
            sb.append(LINEND);
            sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);
            sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
            sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
            sb.append(LINEND);
            sb.append(entry.getValue());
            sb.append(LINEND);

        }

        DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
        outStream.write(sb.toString().getBytes());
        // 发送文件数据
        if (files != null)
            for (Map.Entry<String, File> file : files.entrySet()) {
                StringBuilder sb1 = new StringBuilder();
                sb1.append(PREFIX);
                sb1.append(BOUNDARY);
                sb1.append(LINEND);
                sb1.append("Content-Disposition: form-data; name=\"uploadfile\"; filename=\""
                        + file.getValue().getName() + "\"" + LINEND);
                sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND);
                sb1.append(LINEND);
                outStream.write(sb1.toString().getBytes());

                InputStream is = new FileInputStream(file.getValue());
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = is.read(buffer)) != -1) {
                    outStream.write(buffer, 0, len);
                }
                is.close();
                outStream.write(LINEND.getBytes());
            }

        // 请求结束标志
        byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
        outStream.write(end_data);
        outStream.flush();
        // 得到响应码

        int res = conn.getResponseCode();

       //获取服务器返回结果

       InputStream in = conn.getInputStream();
        StringBuilder sb2 = new StringBuilder();
        if (res == 200) {
            int ch;
            while ((ch = in.read()) != -1) {
                sb2.append((char) ch);
            }
        }
        outStream.close();
        conn.disconnect();
        return sb2.toString();
    }

//调用方式如下

public String uploadFile(File f){
        final Map<String, String> params = new HashMap<String, String>();
        params.put("sessionId", "123456");
        final Map<String, File> files = new HashMap<String, File>();
        files.put("uploadfile",f);
        String response=null;
        try {
            response = UploadUtil.post(FAULT_FILEUPLOAD_URL, params, files);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

使用HTTP进行文件下载其实就是获取输入流数据,然后通过输出流写到文件里,主要代码跟上面FTP下载差不多

 

至于使用哪个协议下载好,就要看具体情况了,对个人而言没啥区别

FTP协议是专门用于文件传输的协议,网络传输更加安全

HTTP只是超文本传输协议,最原始的目的仅仅只是为了将超文本的信息(包括图象视频等)传到你的机子上就行了,但是使用方便

发布了107 篇原创文章 · 获赞 196 · 访问量 15万+

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 鲸 设计师: meimeiellie

分享到微信朋友圈

×

扫一扫,手机浏览