前言

  此博客只讲解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下载与上传的更多相关文章

  1. Android开发之下载服务器上的一张图片到本地java代码实现HttpURLConnection

    package com.david.HttpURLConnectionDemo; import java.io.FileOutputStream; import java.io.IOException ...

  2. iOS开发——网络篇——NSURLSession,下载、上传代理方法,利用NSURLSession断点下载,AFN基本使用,网络检测,NSURLConnection补充

    一.NSURLConnection补充 前面提到的NSURLConnection有些知识点需要补充 NSURLConnectionDataDelegate的代理方法有一下几个 - (void)conn ...

  3. SNF开发平台WinForm之六-上传下载组件使用-SNF快速开发平台3.3-Spring.Net.Framework

    6.1运行效果: 6.2开发实现: 1.先在要使用的项目进行引用,SNF.WinForm.Attachments.dll文件. 2.在工具箱内新建选项卡->选择项,浏览找到文件SNF.WinFo ...

  4. ios开发之网络数据的下载与上传

    要实现网络数据的下载与上传,主要有三种方式 > NSURLConnection  针对少量数据,使用“GET”或“POST”方法从服务器获取数据,使用“POST”方法向服务器传输数据; > ...

  5. iOS开发中文件的上传和下载功能的基本实现-备用

    感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传 ...

  6. Android Http实现文件的上传和下载

    最近做一个项目,其中涉及到文件的上传和下载功能,大家都知道,这个功能实现其实已经烂大街了,遂.直接从网上荡了一堆代码用,结果,发现网上的代码真是良莠不齐,不是写的不全面,就是有问题,于是自己重新整理了 ...

  7. iOS开发——网络Swift篇&NSURLSession加载数据、下载、上传文件

    NSURLSession加载数据.下载.上传文件   NSURLSession类支持三种类型的任务:加载数据.下载和上传.下面通过样例分别进行介绍.   1,使用Data Task加载数据 使用全局的 ...

  8. 斗牛app上架应用宝、牛牛手机游戏推广、百人牛牛app应用开发、棋牌游戏上传、手游APP优化

    联系QQ:305-710439斗牛app上架应用宝.牛牛手机游戏推广.百人牛牛app应用开发.棋牌游戏上传.手游APP优化 iOS开发iPhone/iPad平台安卓手机软件开发机型覆盖范围 超过113 ...

  9. Retrofit实现图文上传至服务器

    Retrofit实现图文上传至服务器 前言:现在大多数的项目中都涉及图片+文字上传了,下面请详见实现原理: 开发环境:AndroidStudio 1.引入依赖: compile 'com.square ...

随机推荐

  1. 并发编程(二)——利用Process类开启进程、僵尸进程、孤儿进程、守护进程、互斥锁、队列与管道

    Process类与开启进程.守护进程.互斥锁 一.multiprocessing模块 1.multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模 ...

  2. 整合phoenix4.6.0-HBase-1.0到cdh5..4.7 编译phoenix4.6源码 RegionServer 宕机

    Phoenix 集成HBase Phoenix 版本:phoenix-4.6.0-HBase-1.0 源码下载地址: http://apache.cs.uu.nl/phoenix/phoenix-4. ...

  3. scala 基础笔记

    view bound:必须传入一个隐式转换函数 class [T <% Ordered [T]] content bound:必须传入一个隐式值 class [T : Ordering] !异步 ...

  4. 【HDOJ】P2058 The sum problem

    题意很简单就是给你一个N和M,让你求在1-N的那些个子序列的值等于M 首先暴力法不解释,简单超时 再仔细想一想可以想到因为1-N是一个等差数列,可以运用我们曾经学过的只是来解决 假设开始的位置为s,结 ...

  5. D3.js 动画 过渡效果 (V3版本)

    一 . 过渡的启动   启动过渡效果,与以下四个方法相关:   d3.transition([selection],[name]) //创建一个过渡对象.但是由于每个选择集中都有transition( ...

  6. mysql数据库 --数据类型、约束条件

    今日内容 表的详细使用 1.创建表的完成语法 2.字段类型 整型.浮点型.字符类型.日期类型.枚举与集合类型 3.约束条件 primary key.unique.not null.default 一. ...

  7. yppasswd, ypchfn, ypchsh - 修改你在NIS数据库中的密码

    SYNOPSIS(总览) yppasswd [-f] [-l] [-p] [user] ypchfn [user] ypchsh [user] DESCRIPTION(描述) 在Linux中,标准的 ...

  8. 文件 IO

    io分类 在文件IO 中是通过文件描述符操作文件的,实际上是一个非负整数 头文件   #include <sys/types.h>   #include <sys/stat.h> ...

  9. c++ exit() 函数

    函数用法 编辑 函数名: exit() 所在头文件:stdlib.h(如果是”VC6.0“的话头文件为:windows.h) 功 能: 关闭所有文件,终止正在执行的进程. exit(0)表示正常退出, ...

  10. FFmpeg Download

    https://ffmpeg.zeranoe.com/builds/