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只是超文本传输协议,最原始的目的仅仅只是为了将超文本的信息(包括图象视频等)传到你的机子上就行了,但是使用方便
Android开发-使用FTP协议和HTTP协议进行文件下载和上传相关推荐
- FTP 协议和 HTTP 协议的比较
参考:http://www.oschina.net/news/28162/http-vs-ftp 以下列出了一些两者的不同点: 1.HTTP协议是用来浏览网站的,而FTP是用来访问和传输文件的,FTP ...
- 网络协议丨FTP协议和P2P协议
现在不管是下载文件还是浏览内容,我们都是使用HTTP协议. 但是除了HTTP协议以外,也存在其他的协议. 比如文件下载,就有FTP协议,也就是文件传输协议.FTP 采用两个 TCP 连接来传输一个文件 ...
- Android网络功能开发(4)——文件下载和上传
本篇介绍使用HTTP协议实现文件下载和上传.在客户端和服务器的通信过程中,可能有些多媒体或数据文件需要下载或上传,可以通过HTTP协议实现. 首先看使用HTTP协议下载文件的原理:客户端发送一个HTT ...
- tcp协议和udp协议区别_TCP和UDP协议有什么区别?
tcp协议和udp协议区别 TCP and UDP are two protocols that are part of the transport layer in a TCP/IP model o ...
- SSL协议和SET协议
SSL协议和SET协议 --三.安全电子交易的协议 --目前的安全电子交易协议主要有两种,即安全套接层(SSL)协议和安全电子交易(SET)协议. --1.SSL协议 --SSL协议由Netscape ...
- 计算机网络整理:UDP协议和TCP协议
系列文章目录 HTTP协议和HTTPS协议 文章目录 系列文章目录 一.TCP/IP 各层协议 二.UDP协议和TCP协议 1.TCP和UDP的区别 2.UDP 协议 3.TCP 协议 1)特点 2) ...
- RabbitMQ MQTT协议和AMQP协议
RabbitMQ MQTT协议和AMQP协议 1 序言... 1 1.1 RabbitMq结构... 1 1.2 RabbitMq消息接收... 4 1.3 Ex ...
- 计算机网络(二十)-广域网-PPP协议和HDLC协议
一.广域网 广域网,通常跨接很大的物理范围,所覆盖的范围从几十公里到几千公里,它能连接多个城市或国家,远距离通信,形成国际性的远程网络. 广域网的通信子网主要使用分组交换技术.广域网的通信子网可以利用 ...
- STM8单片机串口同时识别自定义协议和Modbus协议
在单片机开发中,串口是最常用的和外界交换数据的渠道,要使用串口,那必不可少的就是通信协议,通信协议就是单片机和外界通信的语言,要想正常和其他设备正常交流,首先语言必须相通. 在实际开发过程中由 ...
最新文章
- C#精粹,一本都不能少
- 设计模式 — 行为型模式 — 中介者模式
- Word 2010中利用尾注添加参考文献(论文必备)
- net-snmp交叉编译出现 undefined reference to dlopen,dlsym,dlclose错误
- Nettiers快速使用入门(一) 数据库
- 2014年第五届蓝桥杯C/C++ A组国赛 —— 第一题:海盗分金币
- ActiveMQ性能测试
- 34tomcat设置默认页面
- 可以运行python的路由器_用python管理Cisco路由器
- iOS Core Animation Advanced Techniques-图层树
- 2008 r2 server sql 中文版补丁_SQL Server 2008 R2 补丁
- win10无法装载iso文件_win10系统解决方案无法打开iso文件
- linux抓包-tcpdump
- ios UIImageView 部分圆角(加上 borderWidth、borderColor 效果修复)
- 表格识别综述与相关实战
- 最简单代码画的五角星
- 中盈Zonewin NX-1900 打印机驱动
- Linux系列之CentOS系统安装
- CentOS 环境下的一些配置(安装软件)
- Windows 配置Java环境