关于Android或Java的Http get,post请求的例子和做法还是很多的,本人在项目中没有使用第三方的类库,利用了Android原生类库HttpURLConnection做了一次文件上传,代码逻辑不复杂,就是要理解Http协议的过程和耐心+细心的调试:下面是一个实战例子,测试成功:
如需了解Http文件上传中Http 协议的原理:请参考本人的另外一篇文章:
从HTTP的multipart/form-data分析看C#后台 HttpWebRequest文件上传
https://blog.csdn.net/elie_yang/article/details/80710059
这里再写一个Java版本的文件上传:
public static String upload(String uploadUrl,String fileName, Map<String,String> map, byte[] bytesData) {
try {
final String newLine = "\r\n"; // 换行符
final String boundaryPrefix = "--"; //边界前缀
// 定义数据分隔线
final String boundary = String.format("=========%s",System.currentTimeMillis());
URL url = new URL(uploadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求头参数
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("Charsert", "UTF-8");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
OutputStream out = new DataOutputStream(conn.getOutputStream());
String keyValue = "Content-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n";
byte[] parameterLine= (boundaryPrefix+boundary+newLine).getBytes();
//构建请求参数
if(map!=null&&map.size()>0){
for (Entry<String, String> e : map.entrySet()) {
byte[] keyValueBytes = String.format(keyValue,e.getKey(),e.getValue()).getBytes();
out.write(parameterLine);
out.write(keyValueBytes);
}
}
StringBuilder sb = new StringBuilder();
sb.append(boundaryPrefix);
sb.append(boundary);
sb.append(newLine);
// 文件参数
sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + fileName + "\"" + newLine);
sb.append("Content-Type:application/octet-stream");
// 参数头设置完以后需要两个换行,然后才是参数内容
sb.append(newLine);
sb.append(newLine);
// 将参数头的数据写入到输出流中
out.write(sb.toString().getBytes());
// InputStream inputStream = FormatTools.getInstance().Byte2InputStream(bytesData);
// // 数据输入流,用于读取文件数据
// DataInputStream in = new DataInputStream(inputStream);
// byte[] bufferOut = new byte[1024];
// int bytes = 0;
// // 每次读1KB数据,并且将文件数据写入到输出流中
// while ((bytes = in.read(bufferOut)) != -1) {
// out.write(bufferOut, 0, bytes);
// }
out.write(bytesData);
// 最后添加换行
out.write(newLine.getBytes());
// in.close();
// 定义最后数据分隔线,即--加上boundary再加上--。
byte[] end_data = (newLine + boundaryPrefix + boundary + boundaryPrefix + newLine).getBytes();
// 写上结尾标识
out.write(end_data);
out.flush();
out.close();
// 定义BufferedReader输入流来读取URL的响应
StringBuffer sbOutPut=new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
sbOutPut.append(line);
}
return sbOutPut.toString();
} catch (Exception e) {
System.out.println("发送POST请求出现异常!" + e);
e.printStackTrace();
return null;
}
}
接下来的问题是:Android UI主线程直接发起网络请求时会报错:
有段英文描述说的很明白:The exception that is thrown when an application attempts to perform a networking operation on its main thread.
意思是:当应用程序在主线程里尝试执行一个网络操作时会得到这个错误:解决办法很多,例如Handler post Message或AysncTask等;例如下面的代码:
private class UploadImageTask extends AsyncTask {
@Override
protected Object doInBackground(Object[] objects) {
String requestHost = mcontext.getString(R.string.host_url);
ShareFileHelper fh = new ShareFileHelper();
Bitmap bmp = ScreenShot.takeScreenShot(view);
return fh.uploadImage(requestHost,"abc_456.jpg", bmp);
}
@Override
protected void onPostExecute(Object obj) {
String urlResult = obj.toString();
txtUrl.setText(urlResult);
Bitmap bitmap = QRCodeUtil.createQRCodeBitmap(urlResult,300,300);
imageView.setImageBitmap(bitmap);
super.onPostExecute(obj);
}
}
上面是一段上传图片,并生产二维码的过程。写到这里有一个思考:如果程序中有大量的网络请求需要也要这样定义大量AsyncTask子类吗?是否有HttpUrlConnection的异步执行方式,例如 asyncExecute(). 这样可以简化UI线程的代码量。调用也十分方便。可是SDK库没有这样的接口,百度得来可以对HttpURLConnection进行异步封装,也是把Thread的调用封装到请求中,实际执行没有测试过:
贴代码参考:
参考源:对android HttpUrlConnection的轻量级封装(仿xutils3)
https://blog.csdn.net/qq_35596407/article/details/52528412
private static Handler handler = new Handler();
public static void get(final Map strMap, final String strUrl, final HttpCallBack callBack) {
Thread thread = new Thread() {
@Override
public void run() {
HttpURLConnection connection = null;
InputStream is = null;
try {
StringBuilder stringBuffer = new StringBuilder(strUrl);
stringBuffer.append("?");
for (Object key : strMap.keySet()) {
stringBuffer.append(key + "=" + strMap.get(key) + "&");
}
stringBuffer.deleteCharAt(stringBuffer.length() - 1);
URL url = new URL(stringBuffer.toString());
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(10 * 1000);
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
is = connection.getInputStream();
final String result = InputStreamToString(is);
handler.post(new Runnable() {
@Override
public void run() {
callBack.onSuccess(result);
}
});
} else {
throw new Exception("ResponseCode:" + connection.getResponseCode());
}
} catch (final Exception e) {
e.printStackTrace();
handler.post(new Runnable() {
@Override
public void run() {
callBack.onError(e);
}
});
} finally {
if (connection != null) connection.disconnect();
if (is != null) try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
@Override
public void run() {
callBack.onFinish();
}
});
}
}
};
thread.start();
}
public static void post(final Map strMap, final String strUrl, final HttpCallBack callBack) {
Thread thread = new Thread() {
@Override
public void run() {
HttpURLConnection connection = null;
OutputStream os = null;
InputStream is = null;
try {
StringBuilder stringBuilder = new StringBuilder();
for (Object key : strMap.keySet()) {
stringBuilder.append(key + "=" + strMap.get(key) + "&");
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
URL url = new URL(strUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(10 * 1000);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Charset", "utf-8");
connection.connect();
os = connection.getOutputStream();
os.write(stringBuilder.toString().getBytes());
os.flush();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
is = connection.getInputStream();
final String result = InputStreamToString(is);
handler.post(new Runnable() {
@Override
public void run() {
callBack.onSuccess(result);
}
});
} else {
throw new Exception("ResponseCode:" + connection.getResponseCode());
}
} catch (final Exception e) {
handler.post(new Runnable() {
@Override
public void run() {
callBack.onError(e);
}
});
} finally {
if (connection != null) connection.disconnect();
try {
if (is != null) is.close();
if (os != null) os.close();
} catch (IOException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
@Override
public void run() {
callBack.onFinish();
}
});
}
}
};
thread.start();
}
public static String InputStreamToString(InputStream is) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int len = -1;
while ((len = is.read(data)) != -1) {
os.write(data, 0, len);
}
os.flush();
os.close();
String result = new String(data, "UTF-8");
return result;
}
public interface HttpCallBack {
public void onSuccess(String result);
public void onError(Exception e);
public void onFinish();
}
附加一个利用URLConnection的Post和Get请求:
public static String sendPost(String url, String param) {
String charset = "utf-8";
PrintWriter out = null;
BufferedReader in = null;
String result = "";
String line;
StringBuffer sb=new StringBuffer();
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性 设置请求格式
conn.setRequestProperty("contentType", charset);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//设置超时时间
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应 设置接收格式
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(),charset));
while ((line = in.readLine()) != null) {
sb.append(line);
}
result=sb.toString();
} catch (Exception e) {
System.out.println("发送 POST请求出现异常!"+e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
public static String sendGet(String url, String param) {
String result = "";
String charset = "utf-8";
String line;
StringBuffer sb=new StringBuffer();
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性 设置请求格式
conn.setRequestProperty("contentType", charset);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//设置超时时间
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
// 建立实际的连接
conn.connect();
// 定义 BufferedReader输入流来读取URL的响应,设置接收格式
in = new BufferedReader(new InputStreamReader(
conn.getInputStream(),charset));
while ((line = in.readLine()) != null) {
sb.append(line);
}
result=sb.toString();
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}