Android开发 retrofit下载与上传
前言
此博客只讲解retrofit下载与上传的使用,其实与其说是retrofit的下载与上传还不如说,依然是Okhttp的下载与上传.如果你需要了解retrofit入门请查看这篇博客(此博客不在详细讲解一些基础的东西):https://www.cnblogs.com/guanxinjing/p/11594249.html
下载
设置下载接口
public interface HttpList {
@Streaming //注解这个请求将获取数据流,此后将不会这些获取的请求数据保存到内存中,将交与你操作.
@GET
Call<ResponseBody> download(@Url String url);
}
这里有一个很重要的东西! @Url属性, 这个属性是你导入的下载地址. 它可以是绝对地址和可以是相对地址,当你使用这个属性的时候,Retrofit设置基础Url的baseUrl("http://p.gdown.baidu.com/") 将自动判断地址是绝对还是相对,从而选择拼接Url还是替换Url !
请求下载
private void downloadFile() {
final File file = new File(getExternalCacheDir(), "demo.apk");
if (file.exists()) {
file.delete();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://p.gdown.baidu.com/")//base的网络地址
.callbackExecutor(Executors.newSingleThreadExecutor())//设置线程,如果不设置下载在读取流的时候就会报错
.build();
HttpList httpList = retrofit.create(HttpList.class);
Call<ResponseBody> call = httpList.download(DOWNLOAD_URL_PATH);//下载地址 太长了所以我用DOWNLOAD_URL_PATH封装了一下,不要误解
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
long total = response.body().contentLength();//需要下载的总大小
long current = 0;
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes, 0, len);
fileOutputStream.flush();
current = current + len;
Log.e(TAG, "已经下载=" + current + " 需要下载=" + total);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
以上的下载实现的关键点,其实是ResponseBody,而这个其实就是okhttp的请求接口后返回的响应body. Retrofit并没有对这个进行封装,所以如果你了解okhttp的使用,应该是轻轻松松的.
上传
上传一般有好几种情况:
- 不需要进度的上传
- 需要进度的上传
- 批量上传
无进度的文件上传
接口服务类
public interface HttpList {
@Multipart
@POST("test/upfile")
Call<ResponseBody> upFile(@Part MultipartBody.Part part);
}
注意这里的Body是 MultipartBody
上传实现
/**
* 无进度上传
*/
private void updateFile(){
final File imageFile = new File(getExternalCacheDir() + "/image/demo.jpg");
if (!imageFile.getParentFile().exists()){
imageFile.getParentFile().mkdirs();
} Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.doclever.cn:8090/mock/5ba0c147fa08107daa8c55c2/")
.callbackExecutor(Executors.newSingleThreadExecutor())
.build();
HttpList list = retrofit.create(HttpList.class); //
/*
* "image/jpg" 是你要上传的文件的格式 这个格式并不是固定的,是根据你的项目使用那些何种key也有很多是使用下面这个:
* RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile);
*/
RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpg"), imageFile); //注意这里的file是对应MultipartBody上传文件的key名称
MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("file", imageFile.getName(), requestFile); Call<ResponseBody> call = list.upFile(multipartBody);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.e(TAG, "onResponse: 上传成功 "+response.body().string());
} catch (IOException e) {
e.printStackTrace();
} } @Override
public void onFailure(Call<ResponseBody> call, Throwable t) { }
}); }
有进度的文件上传
/**
* 有进度的上传
*/
private void updateFile(){
final File imageFile = new File(getExternalCacheDir() + "/image/demo.jpg");
if (!imageFile.getParentFile().exists()){
imageFile.getParentFile().mkdirs();
} Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.doclever.cn:8090/mock/5ba0c147fa08107daa8c55c2/")
.callbackExecutor(Executors.newSingleThreadExecutor())
.build();
HttpList list = retrofit.create(HttpList.class);
RequestBody requestFile = new RequestBody() {
@Nullable
@Override
public MediaType contentType() {
return MediaType.parse("image/jpg");//这里返回上传的格式 根据项目情况也可以切换成"multipart/form-data" 等等其他格式
} @Override
public void writeTo(BufferedSink sink) throws IOException {
RandomAccessFile randomAccessFile = new RandomAccessFile(imageFile, "rw");
long totalLength = 0;
long currentUpLength = 0;
if (totalLength == 0) {
totalLength = randomAccessFile.length();
}
byte[] bytes = new byte[2048];
int len = 0;
try {
while ((len = randomAccessFile.read(bytes)) != -1) {
sink.write(bytes, 0, len);
currentUpLength = currentUpLength + len;
Log.e(TAG, "writeTo: totalLength="+totalLength + " currentUpLength="+currentUpLength);
}
}catch (Exception e){
Log.e(TAG, "上传中断");
}finally {
randomAccessFile.close();//关闭流
Log.e(TAG, "流关闭");
} }
}; MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("file", imageFile.getName(), requestFile); Call<ResponseBody> call = list.upFile(multipartBody);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.e(TAG, "onResponse: 上传成功 "+response.body().string());
} catch (IOException e) {
e.printStackTrace();
} } @Override
public void onFailure(Call<ResponseBody> call, Throwable t) { }
}); }
批量上传文件(无对应key的批量上传)
接口服务类
public interface HttpList {
@Multipart
@POST("test/upfileList")
Call<ResponseBody> upFileList(@Part List<MultipartBody.Part> partList);
}
其他与单个上传一致
批量上传文件(有对应key的批量上传)
接口服务类
public interface HttpList {
@Multipart
@POST("test/upfileList")
Call<ResponseBody> upFileList(@PartMap Map<String, RequestBody> map);
}
实现批量上传
private void updateFile3(){
final File imageFile1 = new File(getExternalCacheDir() + "/image/demo_1.jpg");
final File imageFile2 = new File(getExternalCacheDir() + "/image/demo_2.jpg");
final File imageFile3 = new File(getExternalCacheDir() + "/image/demo_3.jpg");
RequestBody requestFile1 = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile1);
RequestBody requestFile2 = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile2);
RequestBody requestFile3 = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile3);
Map<String, RequestBody> map = new HashMap<>();
map.put("file1", requestFile1); //file1 就是需要上传每个文件的key名称
map.put("file2", requestFile2);
map.put("file3", requestFile3);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.doclever.cn:8090/mock/5ba0c147fa08107daa8c55c2/")
.callbackExecutor(Executors.newSingleThreadExecutor())
.build();
HttpList list = retrofit.create(HttpList.class);
Call<ResponseBody> call = list.upFileList(map);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//上传成功
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
end
Android开发 retrofit下载与上传的更多相关文章
- Android开发之下载服务器上的一张图片到本地java代码实现HttpURLConnection
package com.david.HttpURLConnectionDemo; import java.io.FileOutputStream; import java.io.IOException ...
- iOS开发——网络篇——NSURLSession,下载、上传代理方法,利用NSURLSession断点下载,AFN基本使用,网络检测,NSURLConnection补充
一.NSURLConnection补充 前面提到的NSURLConnection有些知识点需要补充 NSURLConnectionDataDelegate的代理方法有一下几个 - (void)conn ...
- SNF开发平台WinForm之六-上传下载组件使用-SNF快速开发平台3.3-Spring.Net.Framework
6.1运行效果: 6.2开发实现: 1.先在要使用的项目进行引用,SNF.WinForm.Attachments.dll文件. 2.在工具箱内新建选项卡->选择项,浏览找到文件SNF.WinFo ...
- ios开发之网络数据的下载与上传
要实现网络数据的下载与上传,主要有三种方式 > NSURLConnection 针对少量数据,使用“GET”或“POST”方法从服务器获取数据,使用“POST”方法向服务器传输数据; > ...
- iOS开发中文件的上传和下载功能的基本实现-备用
感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传 ...
- Android Http实现文件的上传和下载
最近做一个项目,其中涉及到文件的上传和下载功能,大家都知道,这个功能实现其实已经烂大街了,遂.直接从网上荡了一堆代码用,结果,发现网上的代码真是良莠不齐,不是写的不全面,就是有问题,于是自己重新整理了 ...
- iOS开发——网络Swift篇&NSURLSession加载数据、下载、上传文件
NSURLSession加载数据.下载.上传文件 NSURLSession类支持三种类型的任务:加载数据.下载和上传.下面通过样例分别进行介绍. 1,使用Data Task加载数据 使用全局的 ...
- 斗牛app上架应用宝、牛牛手机游戏推广、百人牛牛app应用开发、棋牌游戏上传、手游APP优化
联系QQ:305-710439斗牛app上架应用宝.牛牛手机游戏推广.百人牛牛app应用开发.棋牌游戏上传.手游APP优化 iOS开发iPhone/iPad平台安卓手机软件开发机型覆盖范围 超过113 ...
- Retrofit实现图文上传至服务器
Retrofit实现图文上传至服务器 前言:现在大多数的项目中都涉及图片+文字上传了,下面请详见实现原理: 开发环境:AndroidStudio 1.引入依赖: compile 'com.square ...
随机推荐
- apach hadoop2.6 集群利用Phoenix 4.6-hbase 批量导入并自动创建索引
基础环境: 1.安装apach 版本hadoop2.6 2.部署hbase1.0.0 3.下载phoenix-4.6.0-HBase-1.0.下载地址(http://mirror.nus.edu.sg ...
- C# WinFrom 关于MDI
dev是一个牛B 到没边的控件 我们正常用winform做个原始mdi窗体 一点都不好看 但 用的dev只需要一个控件 就可让显示舒服多了 建一个项目 上边放一个 xtraTabbedMdiManag ...
- UIPageViewController看这篇就够了
先说初始化 - (UIPageViewController *)PageViewController{ if(!_PageViewController){ //书脊位置,只有在UIPageViewCo ...
- 【第二次个人作业】结对作业Core第一组:四则运算生成PB16061082+PB16120517
[整体概况] 1.描述最终的代码的实现思路以及关键代码. 2.结对作业两个人配合的过程和两个人分工. 3.API接口文档和两个组的对接. 4.效能分析,优化分析和心得体会. [代码实现] 一. 实现功 ...
- json条件查询
完整Demo <html> <head> <script type="text/javascript" src="http://www.w3 ...
- 完美编译街机模拟器MAME(Android版)基于MAME4all
重新编译MAME4droid源码 github上开源项目MAME4all可将MAME模拟器运行在iOS和Android上,还有一个比较有名的叫MAME4droid(MAME for android), ...
- boost asio tcp 多线程异步读写,服务器与客户端。
// server.cpp #if 0 多个线程对同一个io_service 对象处理 用到第三方库:log4cplus, google::protobuf 用到C++11的特性,Windows 需要 ...
- 深度探索C++对象模型读书笔记-第六章执行期语意学
在函数中,编译器会帮助将析构函数(Destructor) 安插在相应的位置.对于函数中的局部对象,会将析构函数安插在对象的每一个离开点. 例如: 1: void Function(int a) { 2 ...
- Effective C++之条款2:尽量以const enum inline替换 #define
本文的标题也可以改成“用编译器替换预处理器”: const double AspectRatio = 1.653; //最好使用上述代码替换下述代码: #define ASPECT_RATIO 1.6 ...
- Codeigniter设置时区
Codeigniter 3.x,在application/config/config.php 末尾加上 date_default_timezone_set("Asia/Shanghai&qu ...