本篇将使用OkHttp实现文件的上传和下载,以及下载实现断点续传功能。因为是基本的使用,此系列文章主要是以大家会用为主而写的。当然,只要会用了,后面的优化、封装等等就不难了。
使用OkHttp完成下载功能,实现断点续传,并附带进度条显示下载进度。
文件下载的交互过程:
下载的流程:
复制代码
以上是文件下的代码。实现了断点续传,其中能进行断点续传的关键代码为builder.header("Range", "bytes=" + size + "-");代码中都有注释,结合上面的流程图应该不难理解。
代码解释:源码的效果是点击开始按钮出发click事件开始下载,点击停止按钮触发click2事件中断下载。下载的进度监听是在while循环中,通过Handler进行的进度更新。
本案例中,实现带参数的文件上传功能-----同时完成参数传递和文件上传。
代码如下:
public class UploadActivity extends AppCompatActivity {
public static final int GET_PIC = 1;
private ImageView mShowImage;
private Uri uri;
OkHttpClient okHttpClient = new OkHttpClient();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload);
mShowImage = (ImageView) findViewById(R.id.upload_show_image);
}
public void click(View view) {
switch (view.getId()) {
case R.id.upload_choose_file:
choosePic();//选择图片
break;
case R.id.upload_start:
upload();//上传
break;
}
}
/**
* 上传
*/
private void upload() {
if (uri == null) {
Toast.makeText(UploadActivity.this, "请先选择文件", Toast.LENGTH_SHORT).show();
return;
}
//设置文件的媒体类型,image/*表示匹配所有的图片文件
MediaType mediaType = MediaType.parse("image/*");
MultipartBody.Builder builder = new MultipartBody.Builder();
//文件上传,此处是关键,设置媒体类型为multipart/form-data,表示多种格式的表单数据上传
builder.setType(MultipartBody.FORM);
//添加上传的参数username=androidxx
builder.addFormDataPart("username","androidxx");
//添加上传的文件。文件是从相册读取的文件流。
try {
//获得需要上传的文件流
InputStream inputStream = getContentResolver().openInputStream(uri);
int len = 0;
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((len = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
inputStream.close();
/*
* 添加文件到Builder中。如果要实现多文件同时上传,可以添加多个addFormDataPart。
* 注意:
* 参数一:上传的文件的标示,同username。也就是可以在服务器端通过upload找到对应的文件流
* 参数二:文件的名称。上传到服务器之后以此名称命名文件
* 参数三:需要上传的文件。包含在RequestBody中
* RequestBody.create方法有多个重载的方法,可以选择不同的数据源。此处选择的是字节形式(baos.toByteArray())的数据眼。
*/
builder.addFormDataPart("upload", "test.jpg", RequestBody.create(mediaType, baos.toByteArray()));
} catch (IOException e) {
e.printStackTrace();
}
//创建MultipartBody对象,MultipartBody是RequestBody的子类,用于文件上传。
MultipartBody multipartBody = builder.build();
Request request = new Request.Builder()
.url("http://192.168.3.4:8080/WebServer/upload.do")//上传的服务器地址
.post(multipartBody)
.build();
//开始上传。采用Post异步请求的方式
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d("androidxx.cn","--" + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//接受到成功的返回结果
if (response.isSuccessful()) {
Log.d("androidxx.cn","-上传成功-");
} else {
Log.d("androidxx.cn","-失败--" + response.body().string());
}
}
});
}
/**
* 打开相册,选择文件后返回
*/
private void choosePic() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent,GET_PIC);
}
/**
* 接收选择的图片
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_CANCELED) {
return;
}
//获得图片的URI
uri = data.getData();
//通过ContentResolver获得图片对象
ContentResolver contentResolver = getContentResolver();
InputStream inputStream = null;
try {
inputStream = contentResolver.openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//将流转换成图片,显示到ImageView中
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
mShowImage.setImageBitmap(bitmap);
}
}
复制代码如上代码,第37行和第59行是上传能成功的重点。
实现多文件上传,只需将上面单文件上传中的builder.addFormDataPart("upload", "test.jpg", RequestBody.create(mediaType, baos.toByteArray()));这一句执行多次,即使用多个addFormDataPart方法添加多个文件,然后就可以同时上传多个文件了。
1、文件上传和下载的过程其实就是一种特殊的Post和Get请求。总体的过程与Post请求和Get请求方式一样。
2、下载相当于一个特殊的Get请求,只是服务器返回的数据格式是文件流。我们也只能通过读取流来获得数据。
3、上传相当于一个特殊的Post请求,前面我们说过,Post请求就是传参数比较特殊和多样化。文件上传就是一种特殊的参数传递----参数是一个文件。
大家在看如上代码的时候,不要觉得陌生,其实代码的流程和逻辑同Post和Get请求一样,只是多了几行代码。
本案例的android端源码:Github
本案例的上传服务器配置方式【点击查看】,上传服务端源码:Github 服务器端代码请阅读Github中的readme.md文件。服务器端代码导入工程没有错之后,可以将代码加载到服务器,之后启动服务器就可以运行。本案例使用的是Tomcat服务器。
备注:对于android程序员如果想运行服务器代码,按照readme.md文档。然后有不懂的,可以留言。
转载请注明:androidxx.cn
最后附上下载效果(注意点击按钮开始和停止后下载进度条的变化,实现断点续传)。