Android开发经常遇到要上传文件,我在网上找了一些文件上传的解决方案,自己做了一个整合。JavaWeb端参考:JavaWeb学习总结(五十)——文件上传和下载
直接上代码:
1,HttpURLConnection上传文件
package com.yyw.mutilthreaddownload; import android.util.Log; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.UUID; /** * HttpURLConnection上传文件 */ public class HttpUpLoad { private static final String TAG = "uploadFile"; private static final int TIME_OUT = 10 * 10000000; // 超时时间 private static final String CHARSET = "utf-8"; // 设置编码 public static final String SUCCESS = "1"; public static final String FAILURE = "0"; /** * * @param params 上传的参数 * @param file 文件 * @param RequestURL url地址 * @return 返回 */ public static String uploadFile(HashMap<String,String>params,File file ,String RequestURL) { String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成 String PREFIX = "--", LINE_END = "\r\n"; String CONTENT_TYPE = "multipart/form-data"; // 内容类型,指定为上传文件 try { URL url = new URL(RequestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(TIME_OUT); conn.setConnectTimeout(TIME_OUT); conn.setDoInput(true); // 允许输入流 conn.setDoOutput(true); // 允许输出流 conn.setUseCaches(false); // 不允许使用缓存 conn.setRequestMethod("POST"); // 请求方式,必须是大写POST,GET conn.setRequestProperty("Charset", CHARSET); // 设置编码 conn.setRequestProperty("connection", "keep-alive"); //在请求头中添加请求的分界符 conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY); if (file != null) { /** * 当文件不为空,把文件包装并且上传 */ OutputStream outputSteam = conn.getOutputStream(); //准备上传文件 DataOutputStream dos = new DataOutputStream(outputSteam); StringBuffer sb = new StringBuffer(); /************************上传表单的一些设置信息***********************************/ if (params != null) for (String key : params.keySet()) { sb.append("--" + BOUNDARY + "\r\n"); sb.append("Content-Disposition: form-data; name=\"" + key + "\"" + "\r\n"); sb.append("\r\n"); sb.append(params.get(key) + "\r\n"); } /************************上传文件的一些设置信息***********************************/ sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); /** * 这里重点注意: name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件 * filename是文件的名字,包含后缀名的 比如:abc.png */ sb.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"" + LINE_END); sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END); sb.append(LINE_END); dos.write(sb.toString().getBytes()); /************************上传文件***********************************/ InputStream is = new FileInputStream(file); byte[] bytes = new byte[1024]; int len = 0; while ((len = is.read(bytes)) != -1) { dos.write(bytes, 0, len); Log.i(TAG, "上传成功 +" + len); } is.close(); /************************上传文件结束后的结束符号***********************************/ dos.write(LINE_END.getBytes()); byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END) .getBytes(); dos.write(end_data); dos.flush(); /** * 获取响应码 200=成功 当响应成功,获取响应的流 */ int res = conn.getResponseCode(); if (res == 200) { //获取返回内容 InputStream input = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String result = reader.readLine(); Log.i(TAG,"上传成功" + result); reader.close(); is.close(); Log.i(TAG,"上传成功 +"+conn.getResponseMessage()); return SUCCESS; } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return FAILURE; } }用 HttpURLConnection上传文件有文件大小的限制。参考:从原理角度解析Android (Java) http 文件上传写了一个demo
package com.yyw.mutilthreaddownload; import android.util.Log; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.Socket; import java.net.URL; import java.util.Map; /** * Created by yyw on 2016/1/19. * 用Socket模拟HTTP上传比较大的文件, */ public class UpBigFile { public static final String TAG = "UpBigFile"; private String charset = "UTF-8"; /** * * @param params 参数 * @param file 文件 * @param url url */ public void upLoadByScoket(Map<String, String> params,File file, String url) { try { String end = "\r\n"; URL mUrl = new URL(url); String param = getParamString(params);//参数 String fileHeader = getFileHeader(file);//文件的头 String fileEnder = getFileEnder();//内容结束 long l = param.length()+fileHeader.length()+fileEnder.length()+3*end.length()+file.length();//内容的长度 String header = getHeaderString(url, mUrl,l);//请求头 Socket mSocket = new Socket(mUrl.getHost(),mUrl.getPort());//用Socket模拟HTTP请求 OutputStream os = mSocket.getOutputStream(); PrintStream ps = new PrintStream(os,true,charset); Log.d(TAG, "upLoadByScoket: " + header); ps.print(header); ps.print(end); ps.print(param); ps.print(end); ps.print(fileHeader); ps.print(end); FileInputStream is = new FileInputStream(file); byte[] buffer = new byte[1024]; int len = -1; int count = 0; while ((len = is.read(buffer))!=-1){ count += len; Log.i(TAG,"上传成功 +"+count); os.write(buffer,0,len); } os.flush(); ps.print(end); ps.print(fileEnder); InputStream input = mSocket.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String result = reader.readLine();//返回内容 Log.i(TAG, "上传成功" + result); reader.close(); is.close(); os.close(); ps.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 文件开始符号 * @param file * @return */ private String getFileHeader(File file){ String boundary = "******"; String end = "\r\n"; StringBuilder builder = new StringBuilder(); builder.append("--"); builder.append(boundary); builder.append(end); builder.append("Content-Disposition: form-data; name=\"file\";filename =\""+file.getName()+"\""+end); builder.append("Content-Type: application/octet-stream; Charset="); builder.append(charset); builder.append(end); return builder.toString(); } /** * 内容结束符号 * @return 内容结束符号 */ private String getFileEnder(){ String boundary = "******"; String end = "\r\n"; return "--" + boundary + "--" + end; } /** * 获取请求的表单参数字符串 * @param params 参数内容 * @return 请求的表单参数字符串 */ private String getParamString(Map<String, String> params) { String boundary = "******"; StringBuilder param = new StringBuilder(); if (params != null) for (String key : params.keySet()) { param.append("--" + boundary + "\r\n"); param.append("Content-Disposition: form-data; name=\"" + key + "\"" + "\r\n"); param.append("\r\n"); param.append(params.get(key) + "\r\n"); } return param.toString(); } /** * 获取上传的请求头(模仿HTTP请求头) * @param url 地址 * @param mUrl 地址URL * @param length 上传内容的长度 * @return 上传请求头 */ private String getHeaderString(String url, URL mUrl,long length) { String end = "\r\n"; String connection = "keep-alive"; String contentType = "multipart/form-data"; String boundary = "******"; // POST http://192.168.0.55:8082/LearnNew/servlet/UploadHandleServlet HTTP/1.1 // Charset: UTF-8 // connection: keep-alive // Content-Type: multipart/form-data;boundary=****** // User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.1.1; GT-N8000 Build/JRO03C) // Host: 192.168.0.55:8082 // Accept-Encoding: gzip // Content-Length: 2484 StringBuilder header = new StringBuilder(); header.append("POST "); header.append(url); header.append(" HTTP/1.1"); header.append(end); header.append("Charset: "); header.append(charset); header.append(end); header.append("connection: "); header.append(connection); header.append(end); header.append("Content-Type: "); header.append(contentType); header.append(";boundary="); header.append(boundary); header.append(end); header.append("User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.1.1; GT-N8000 Build/JRO03C)"); header.append(end); header.append("Host: "); header.append(mUrl.getHost()); header.append(end); header.append("Accept-Encoding: gzip"); header.append(end); header.append("Content-Length: "); header.append(length); header.append(end); header.toString(); return header.toString(); } }上传的信息内容:
POST http://192.168.0.55:8082/LearnNew/servlet/UploadHandleServlet HTTP/1.1 Charset: UTF-8 connection: keep-alive Content-Type: multipart/form-data;boundary=****** User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.1.1; GT-N8000 Build/JRO03C) Host: 192.168.0.55:8082 Accept-Encoding: gzip Content-Length: 2484 --****** Content-Disposition: form-data; name="name" zhangshan --****** Content-Disposition: form-data; name="file";filename ="21_55-1447057315784.log" replacements=[Ljava.lang.String;@40dcc5d0 HARDWARE=hws8301l matchers=[Ljava.lang.String;@40dcc550 RADIO=unknown HOST=screen105 HIDE_PRODUCT_INFO=false TAGS=release-keys PRODUCT_CHARM=MediaPad X1 7.0 ID=HuaweiMediaPad MIN_VERSION_LENGTH=8 MANUFACTURER=HUAWEI TYPE=user TAG=Build TIME=1403853553000 FINGERPRINT=Huawei/MediaPad/hws8301l:4.2.2/HuaweiMediaPad/S8301uV1R1C233B009:user/release-keys UNKNOWN=unknown PRODUCT_8VOGUE=MediaPad M1 8.0 BOARD=BalongV9R1 VERSION_MAX_SIZE=30 properties={ro.build.internal.t.version=S8-301uV100R001C233B009-01, ro.build.cust.id=S8-301uV100R001C233B009, ro.build.operator.id=S8-301uV100R001C233B009} PRODUCT=MediaPad FilePath=/cust/hwver.properties DISPLAY=S8-301uV100R001C233B009 USER=jslave DEVICE=hws8301l MODEL=MediaPad M1 8.0 BOOTLOADER=unknown CPU_ABI=armeabi-v7a PRODUCT_UNKNOWN=unknown CPU_ABI2=armeabi IS_DEBUGGABLE=false SERIAL=A8Z6R14613000263 BRAND=Huawei --******--
Android的一个OkHttp的开源网络访问上传文件会很方便。
/** * 上传文件 * @param url * @param file */ private void upFile(String url,File file){ OkHttpClient client = new OkHttpClient(); RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM).addPart(Headers.of("Content-Disposition", "form-data; name=\"file\";filename =\""+file.getName()+"\""),RequestBody.create(null,file)).build(); Request request = new Request.Builder().post(body).url(url).build(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { String r = response.body().string(); if (response.isSuccessful()) { Log.i(TAG, "httpGet1 OK: " + r); } else { Log.i(TAG, "httpGet1 error: " + r); } } }); }