下面所写内容都有源码都能直接使用可供下载,使用图片下载、上传都是真实有效的地址,可直接使用:
项目下载地址:https://github.com/cmyeyi/NetFramework
okhttp依赖库导入参考上一篇:android 网络3 okhttp(1) get/post基本用法
一个很好的图片压缩网站:https://tinypng.com/ 这里上传图片便依赖此网站,可能需要vpn
1、异步文件下载
文件的下载不需要我们制定是什么访问类型,具体实践操作如下,原理就是从网络上获取所需要下载的文件的流,然后通过IO操作存入本地,下面将要操作从网络上下载一张图片,让后保存在根目录:
private void download() {
String imageUrl = "https://picjumbo.com/wp-content/uploads/abstract-free-photo-1570x1047.jpg";
Request request = new Request.Builder().url(imageUrl).build();
OkHttpClient okHttpClient = new OkHttpClient();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, e.getLocalizedMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e(TAG, response.message());
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = null;
String filePath = "";
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Log.d(TAG, "get file path#1#");
filePath = Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
filePath = getActivity().getFilesDir().getAbsolutePath();
Log.d(TAG, "get file path#2#");
}
Log.d(TAG, "filepath = " + filePath);
File file = new File(filePath, "abstract-free-photo-1570x1047.jpg");
if (!file.exists()) {
fileOutputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, length);
}
fileOutputStream.flush();
}
} catch (IOException e) {
Log.e(TAG, "IOException");
e.printStackTrace();
}
}
});
}
2、异步上传文件
上传文件本质上也是一种post请求
比如我们将要将手机根目录下的一张图片上传到图片压缩网站:https://tinypng.com/web/shrink
public final static MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/png");
public final static String UPLOAD_URL = "https://tinypng.com/web/shrink";
public final static String DEFAULT_PATH = "/storage/emulated/0";
/**
* MediaType是什么
* MediaType在网络协议的消息头里面叫做Content-Type
* 使用两部分的标识符来确定一个类型
* 所以我们用的时候其实就是为了表明我们传的东西是什么类型
* 比如
* application/json:JSON格式的数据,在RFC 4627中定义
* application/javascript:JavaScript,在RFC 4329中定义但是不被IE8以及之前的版本支持
* audio/mp4:MP4音频
* audio/mpeg:MP3 或者MPEG音频,在RFC 3003中定义
* image/jpeg:JPEG 和JFIF格式,在RFC 2045 和 RFC 2046中定义
* image/png:png格式,在 RFC 2083中定义
* text/html:HTML格式,在RFC 2854中定义
* text/javascript :JavaScript在已经废弃的RFC 4329中定义,现在推荐使用“application/javascript”。然而“text/javascript”允许在HTML 4 和5 中使用。并且与“application/javascript”不同,它是可以跨浏览器支持的
*
* @param parent 被上传文件的父路径
* @param child 被上传文件名
*/
private void upload(String parent, String child) {
Log.d(TAG, "#begin upload#");
File file = new File(parent, child);
Request request = new Request.Builder().url(UPLOAD_URL).post(RequestBody.create(MEDIA_TYPE_IMAGE, file)).build();
OkHttpClient okHttpClient = new OkHttpClient();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG,"failure:" + e.getLocalizedMessage());
Log.d(TAG,"#upload over#");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG,"response message|" + response.message());
if(response.isSuccessful()){
Log.d(TAG,"upload success,response|" + response.body().string());
} else {
Log.d(TAG,"upload failure,response|" + response.message());
}
Log.d(TAG,"#upload over#");
}
});
}
private void uploadImage() {
String imageName = "abstract-free-photo-1570x1047.jpg";
String imagePath = DEFAULT_PATH;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
imagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
return;
}
upload(imagePath, imageName);
}
上传完毕之后返回结果如下:
{"input":{"size":198123,"type":"image/jpeg"},"output":{"size":161269,"type":"image/jpeg","width":1570,"height":1047,"ratio":0.814,"url":"https://tinypng.com/web/output/50hyahgdxxnw20w7z854qqqr3tyxav8u"}}
https://tinypng.com/web/output/50hyahgdxxnw20w7z854qqqr3tyxav8u 是处理完毕图片后,新图片的下载地址
3、异步以MultipartBody形式上传文件
其实也就是javaweb上的表单提交等,一次性上传多组数据,包括文件、图片等
这里给一个简单的例子,当然,还是用的上面的url上传地址,肯定是无法通过的,这里仅是说明一下这种通过okhttp3上传服务器的方式,以后再详细说明:
private void uploadMultiFile(String parent, String child) {
Log.d(TAG, "#begin upload multi#");
File file = new File(parent, child);
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "good image")
.addFormDataPart("image", child, RequestBody.create(MEDIA_TYPE_IMAGE, file))
.build();
Request request = new Request.Builder()
.url(UPLOAD_URL)
.post(requestBody)
.build();
OkHttpClient okHttpClient = new OkHttpClient();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "multi failure:" + e.getLocalizedMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "multi response message|" + response.message());
if (response.isSuccessful()) {
Log.d(TAG, "upload multi success,response|" + response.body().string());
} else {
Log.d(TAG, "upload multi failure,response|" + response.message());
}
}
});
}
private void doUploadMultiFile() {
String imageName = "abstract-free-photo-1570x1047.jpg";
String imagePath = DEFAULT_PATH;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
imagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
return;
}
uploadMultiFile(imagePath, imageName);
}