Android使用Https协议与Tomcat服务器进行文件上下传,并将上传的文件上传至HDFS
来源:互联网 发布:剑灵小秦夕妍捏脸数据 编辑:程序博客网 时间:2024/06/05 23:57
最近使用了HTTPS协议在Android设备上进行文件上下传操作,这里做一下记录。
一、Android端代码
1.下面的代码是关于文件上传和下载需要使用的工具类。
这个代码是模仿表单的形式提交文件信息。
package com.example.justyoung.logintest;import android.content.SharedPreferences;import android.util.Log;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.URL;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.util.List;import java.util.Map;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSession;import javax.net.ssl.TrustManager;import javax.net.ssl.X509TrustManager;/** * Created by justyoung on 15/6/28. */public class HttpsHelper { public static final String PREFIX = "--"; public static final String LINE_END = "\r\n"; public static final String BOUNDARY = "*****"; private HttpsURLConnection connection = null; private StringBuilder response = null; public void prepareHttpsConnection(String url) throws KeyManagementException, NoSuchAlgorithmException, IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier()); connection = (HttpsURLConnection) new URL(url).openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setConnectTimeout(10000); } public int uploadFile(String filename) throws IOException { int result = 0; if (filename == null) return result; connection.setUseCaches(false); connection.setRequestMethod("POST"); connection.setRequestProperty("Charset", "utf-8"); connection.setRequestProperty("Connection", "keep-alive"); connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY); DataOutputStream dos = new DataOutputStream(connection.getOutputStream()); dos.writeBytes(PREFIX + BOUNDARY + LINE_END); dos.writeBytes("Content-Disposition: form-data; " + "name=\"file1\";filename=\"" + filename.substring(filename.lastIndexOf("/")) + "\"" + LINE_END); dos.writeBytes(LINE_END); int len; InputStream ins = new FileInputStream(new File(filename)); byte[] buffer = new byte[1024]; while ((len = ins.read(buffer)) != -1) { dos.write(buffer, 0, len); } ins.close(); dos.writeBytes(LINE_END); dos.writeBytes(PREFIX + BOUNDARY + PREFIX + LINE_END); dos.close(); int responseCode = connection.getResponseCode(); if (responseCode == 200) { ins = connection.getInputStream(); int ch; StringBuffer b = new StringBuffer(); while ((ch = ins.read()) != -1) { b.append((char) ch); } Log.i("bbb", b.toString()); } return responseCode; } /** * * @param despath 存储的位置 * @throws IOException */ public void downloadFile(String despath) throws IOException { connection.connect(); InputStream ins = connection.getInputStream(); File file = new File(despath); if (file.exists()){ IOException e = new IOException("File exists"); throw e; } OutputStream out = null; byte[] buffer = new byte[1024]; int len; try { out = new FileOutputStream(file); while ((len = ins.read(buffer)) != -1) { out.write(buffer, 0, len); } out.flush(); } catch (Exception e){ } finally { if (out != null) { try { out.close(); } catch (Exception e){ } } } } private static class MyHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String hostname, SSLSession session) { return true; } } private static class MyTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }}
如果不用表单的方式提交,可以将文件,直接以二进制的形式填入到HTTP报文的BODY部分,如下所示:
public int uploadFile(String filename) throws IOException { int result = 0; if (filename == null) return result; connection.setUseCaches(false); connection.setRequestMethod("POST"); connection.setRequestProperty("Charset", "utf-8"); connection.setRequestProperty("Connection", "keep-alive"); connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY); connection.setRequestProperty("Cookie", "SESSIONID=28e8795c46d736d6b39aadffb653e23c3d0802ba;USERNAME=ylh2"); connection.setChunkedStreamingMode(0); InputStream ins = new BufferedInputStream(new FileInputStream(new File(filename))); BufferedOutputStream bos = new BufferedOutputStream(connection.getOutputStream()); byte[] buffer = new byte[4096]; int len = 0; while((len = ins.read(buffer)) != -1) { bos.write(buffer, 0, len); } ins.close(); bos.flush(); bos.close(); int responseCode = connection.getResponseCode(); if (responseCode == 200) { ins = connection.getInputStream(); int ch; StringBuffer b = new StringBuffer(); while ((ch = ins.read()) != -1) { b.append((char) ch); } Log.i("bbb", b.toString()); } return responseCode; }
2.下面的代码是进行文件上传和下载的线程类,因为Android上的网络操作不能使用UI线程,所以都需要使用其他线程进行。
文件上传的代码如下:
package com.example.justyoung.logintest;import java.io.IOException;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;/** * Created by justyoung on 15/6/30. */public class uploadFile extends Thread { String path; String url; public uploadFile(String path, String url) { this.path = path; this.url = url; } @Override public void run() { HttpsHelper httpsHelper = new HttpsHelper(); try { httpsHelper.prepareHttpsConnection(url); httpsHelper.uploadFile(path); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
上传的代码可以这样调用:
String https = "https://192.168.2.160:8443/CloudStorageServer/uploadfile";String path = "/sdcard/DCIM/Camera/20150429_115313.jpg";uploadFile uploadFile = new uploadFile(path, https);uploadFile.start();
文件下载的代码如下:
package com.example.justyoung.logintest;import java.io.IOException;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;/** * Created by justyoung on 15/7/1. */public class DownloadFile extends Thread { private String url; private String despath; public DownloadFile(String url, String filename, String despath) { this.url = url + "?filename=" + filename; this.despath = despath; } public void run(){ HttpsHelper httpsHelper = new HttpsHelper(); try { httpsHelper.prepareHttpsConnection(url); httpsHelper.downloadFile(despath); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }}
下载的代码可以这样调用:
String https = "https://192.168.2.139:8443/CloudStorageServer/download";String desPath = "/sdcard/DCIM/Camera/123.pdf";DownloadFile df = new DownloadFile(https, "xx.pdf", desPath);df.start();
这里需要注意一个问题:因为使用的是HTTP协议进行传输,所以HTTP报文是一次性做好再发送给服务器,所以大文件上传可能会出现问题,例如:Android读取文件到DataOutputStream中时,就可能会因为占用内存过大而导致程序被强制退出,所以要进行大文件上传时,可以将文件分块后进行上传。
二、服务器端代码
我这里使用的是如下的类来接收Android端上传的文件和向Android端发送的文件,只是,这里将Android上传的文件从内存中直接上传到HDFS上,向Android端发送文件时,直接将文件从HDFS上读取到内存中,然后发送给Android客户端。
下面这个代码是接收模仿表单上传的代码。
package com.cyber_space.businessLogic;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.tomcat.util.http.fileupload.FileItemIterator;import org.apache.tomcat.util.http.fileupload.FileItemStream;import org.apache.tomcat.util.http.fileupload.FileUploadException;import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;import com.cyber_space.HDFSManager.DownloadFromBytes;import com.cyber_space.HDFSManager.HDFSUpload;import com.cyber_space.HDFSManager.UploadFromBytes;import com.cyber_space.util.Log;import com.cyber_space.util.properties.SysProperties;public class FileLogic {public static String TEMP_PATH; // 文件临时目录public static int SIZE_THRESHOLD;public static long SIZE_MAX;static {init();}public static void init() {TEMP_PATH = SysProperties.getValue("file_temp_dir");SIZE_THRESHOLD = Integer.valueOf(SysProperties.getValue("SIZE_THRESHOLD"));SIZE_MAX = Integer.valueOf(SysProperties.getValue("file_size_max"));}public FileLogic() {}/** * 直接从内存中将数据上传至HDFS * * @param request * @throws IOException * @throws FileUploadException */public static void uploadToHDFS(HttpServletRequest request)throws FileUploadException, IOException {DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();diskFileItemFactory.setSizeThreshold(SIZE_THRESHOLD); // 文件临界值diskFileItemFactory.setRepository(new File(TEMP_PATH));ServletFileUpload upload = new ServletFileUpload(diskFileItemFactory);upload.setSizeMax(SIZE_MAX);FileItemIterator items = upload.getItemIterator(request);FileItemStream fileItemStream = null;InputStream inputStream = null;String filename = null;BufferedInputStream bis = null;UploadFromBytes ufb = null;byte[] buffer = new byte[2048];int len = 0;while (items.hasNext()) {fileItemStream = items.next();inputStream = fileItemStream.openStream();if (fileItemStream.isFormField()) {return;}filename = fileItemStream.getName();ufb = new UploadFromBytes(filename);try {bis = new BufferedInputStream(inputStream);while ((len = bis.read(buffer)) != -1) {ufb.writeBytes(buffer, len);}} catch (Exception e) {Log.logException(e);return;} finally {bis.close();ufb.commit();}}}public static void downloadFromHDFS(HttpServletResponse response,String filename) throws IOException {if (response == null || filename == null || filename.equals(""))return;response.setContentType("application/x-msdownload");response.addHeader("Content-Disposition", "attachment;filename="+ filename);ServletOutputStream sos = response.getOutputStream();DownloadFromBytes dfb = null;try {dfb = new DownloadFromBytes(filename);byte[] buffer = new byte[1024];int len = 0;while ((len = dfb.download(buffer)) != -1) {sos.write(buffer, 0, len);}sos.flush();} catch (Exception e) {Log.logException(e);} finally{dfb.close();}}}
如果文件不是以表单的形式从Android端发送,而是直接将二进制信息写在HTTP报文的BODY部分,那么就可以像下面这样接收文件:
/** * 直接从内存中将数据上传至HDFS * * @param request * @throws IOException * @throws FileUploadException */public static boolean upload2HDFS(HttpServletRequest request)throws FileUploadException, IOException {String filename = request.getParameter("filename");if (filename == null || filename.equals(""))return false;ServletInputStream is = null;byte[] buffer = new byte[10240];int totalLength = 0, len = 0;UploadFromBytes ufb = null;try {is = request.getInputStream();ufb = new UploadFromBytes(filename);try {while ((len = is.read(buffer)) != -1) {Log.logger.debug("read and write byte: " + len);ufb.writeBytes(buffer, len);totalLength += len;}} catch (Exception e) {Log.logException(e);DeleteFile deleteHDFSFile = new DeleteFile();deleteHDFSFile.delete(filename);} finally {ufb.commit();}if (totalLength < 1) {DeleteFile deleteHDFSFile = new DeleteFile();deleteHDFSFile.delete(filename);return false;}Log.logger.debug("write chunk byte: " + totalLength);} catch (Exception e) {Log.logException(e);return false;} finally {is.close();}return true;}
下面的代码是HDFS操作的一些基本配置类,将一些配置读取到内存中来,方便下次使用,因为Configration类初始化十分耗时,因此内存中有一份就好了。
package com.cyber_space.HDFSManager;import java.io.IOException;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import com.cyber_space.hdfs.HDFSManager;import com.cyber_space.util.Log;import com.cyber_space.util.properties.SysProperties;public class HDFSUpload {static Configuration conf = new Configuration();static String hdfs_path = SysProperties.getValue("hdfs_path"); // hdfs://namenode:50040static String user_path = SysProperties.getValue("user_path"); // /UserStorage ,这里根据实际情况来做static {conf.set("fs.defaultFS", hdfs_path);conf.set("fs.hdfs.impl",org.apache.hadoop.hdfs.DistributedFileSystem.class.getName());conf.set("fs.file.impl",org.apache.hadoop.fs.LocalFileSystem.class.getName());System.setProperty("hadoop.home.dir", SysProperties.getValue("hadoop_home")); //hadoop_home=/Users/justyoung/Documents/workspace/hadoop-2.7.0}}
下面这段代码是将文件上传到HDFS的工具类。
package com.cyber_space.HDFSManager;import java.io.IOException;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FSDataOutputStream;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import com.cyber_space.util.Log;public class UploadFromBytes {private FSDataOutputStream fsOutputStream = null;private FileSystem hadoopFS = null;private Configuration conf = null;public UploadFromBytes(String despath) throws IOException {despath = HDFSUpload.hdfs_path + HDFSUpload.user_path + despath;conf = HDFSUpload.conf;hadoopFS = FileSystem.get(conf);fsOutputStream = hadoopFS.create(new Path(despath));}public void writeBytes(byte[] bytes, int len) throws IOException {if (bytes == null) {return;}fsOutputStream.write(bytes, 0, len);}public void commit(){try {fsOutputStream.close();fsOutputStream = null;} catch (IOException e) {Log.logException(e);e.printStackTrace();}}}
下面的代码是从HDFS下载文件的工具类:
package com.cyber_space.HDFSManager;import java.io.IOException;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FSDataInputStream;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import com.cyber_space.util.Log;public class DownloadFromBytes {private FileSystem hadoopFS = null;private Configuration conf = null;private FSDataInputStream fsInputStream = null;public DownloadFromBytes(String srcPath) throws IOException {srcPath = HDFSUpload.hdfs_path + HDFSUpload.user_path + "/" + srcPath;conf = HDFSUpload.conf;hadoopFS = FileSystem.get(conf);fsInputStream = hadoopFS.open(new Path(srcPath));}public int download(byte[] ioBuffer) throws IOException {if (ioBuffer == null){IOException e = new IOException("ioBuffer is null");throw e; }return fsInputStream.read(ioBuffer);}public void close() {if (fsInputStream != null) {try {fsInputStream.close();} catch (IOException e) {e.printStackTrace();Log.logException(e);}}}}
上面的代码可在Servlet中调用,例如:
FileLogic.uploadToHDFS(request);FileLogic.downloadFromHDFS(response, filename);
1 0
- Android使用Https协议与Tomcat服务器进行文件上下传,并将上传的文件上传至HDFS
- 上传文件与应用服务器Tomcat分离,并有效的进行跨域回显
- 关于Android客户端与Tomcat服务器的文件上传
- 使用Httpclient(post请求)上传文件及其他参数到https协议的服务器
- Android 拍照上传与选择文件上传至服务器
- HDFS上传文件的命令使用
- android通过HTTP协议上传文件至远程服务器
- 使用flume将avro文件上传到hdfs上
- scala和java解压zip的文件,并上传到hdfs服务器
- Android上传文件至服务器
- Android上传文件至服务器
- Android上传文件至服务器
- Android上传文件至服务器
- Android上传文件至服务器
- Android上传文件至服务器
- Android上传文件至服务器
- Android 文件上传至服务器
- Android上传文件至服务器
- Activity切换动画overridePendingTransition的使用
- ADT 23.0.2找不到Annotation Processing选项,解决方法
- java总结(之一)--容器的基本用法
- 文章标题
- 程序员的“纪律性”
- Android使用Https协议与Tomcat服务器进行文件上下传,并将上传的文件上传至HDFS
- 一个正整数的正因子数
- Linux fork 后 wait 获取子进程结束的状态示例
- HDU 1312 Red and Black
- start from ending
- Mac配置Python开发环境(Eclipse +Pydev+Python)
- java 项目
- JavaScript的全局变量和局部变量
- 浅谈云计算的形态