├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zx │ │ └── okhttp3 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── zx │ │ │ └── okhttp3 │ │ │ ├── MainActivity.java │ │ │ └── OKHttpUtils.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── zx │ └── okhttp3 │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zx │ │ └── uploadlibrary │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── zx │ │ │ └── uploadlibrary │ │ │ ├── helper │ │ │ └── ProgressHelper.java │ │ │ ├── listener │ │ │ ├── ProgressListener.java │ │ │ └── impl │ │ │ │ ├── UIProgressListener.java │ │ │ │ ├── handler │ │ │ │ └── ProgressHandler.java │ │ │ │ └── model │ │ │ │ └── ProgressModel.java │ │ │ ├── progress │ │ │ ├── ProgressRequestBody.java │ │ │ └── ProgressResponseBody.java │ │ │ └── utils │ │ │ └── OKHttpUtils.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── zx │ └── uploadlibrary │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### 一、简介 2 | v1.01版本 3 | 对OKHttp的封装,可实现多文件上传(带进度值)、表单提交到服务器;下载文件保存到到本地(带进度值)。 4 | 可以在文件上传/下载时,在开始、结束、进度回调3个方法中自定义内容。 5 | 6 | #### 二、使用步骤: 7 | 8 | **1、Gradle添加如下2个依赖** 9 | ``` 10 | allprojects { 11 | repositories { 12 | ... 13 | maven { url 'https://jitpack.io' } 14 | } 15 | } 16 | 17 | dependencies { 18 | compile 'com.github.zhouxu88:OkHttp3_MultiFile:v1.0' 19 | } 20 | ``` 21 | 22 | **2、多文件上传的调用** 23 | ``` 24 | //多文件上传(带进度) 25 | private void upload() { 26 | //这个是非ui线程回调,不可直接操作UI 27 | final ProgressListener progressListener = new ProgressListener() { 28 | @Override 29 | public void onProgress(long bytesWrite, long contentLength, boolean done) { 30 | Log.i("TAG", "bytesWrite:" + bytesWrite); 31 | Log.i("TAG", "contentLength" + contentLength); 32 | Log.i("TAG", (100 * bytesWrite) / contentLength + " % done "); 33 | Log.i("TAG", "done:" + done); 34 | Log.i("TAG", "================================"); 35 | } 36 | }; 37 | 38 | 39 | //这个是ui线程回调,可直接操作UI 40 | UIProgressListener uiProgressRequestListener = new UIProgressListener() { 41 | @Override 42 | public void onUIProgress(long bytesWrite, long contentLength, boolean done) { 43 | Log.i("TAG", "bytesWrite:" + bytesWrite); 44 | Log.i("TAG", "contentLength" + contentLength); 45 | Log.i("TAG", (100 * bytesWrite) / contentLength + " % done "); 46 | Log.i("TAG", "done:" + done); 47 | Log.i("TAG", "================================"); 48 | //ui层回调,设置当前上传的进度值 49 | int progress = (int) ((100 * bytesWrite) / contentLength); 50 | uploadProgress.setProgress(progress); 51 | uploadTV.setText("上传进度值:" + progress + "%"); 52 | } 53 | 54 | //上传开始 55 | @Override 56 | public void onUIStart(long bytesWrite, long contentLength, boolean done) { 57 | super.onUIStart(bytesWrite, contentLength, done); 58 | Toast.makeText(getApplicationContext(),"开始上传",Toast.LENGTH_SHORT).show(); 59 | } 60 | 61 | //上传结束 62 | @Override 63 | public void onUIFinish(long bytesWrite, long contentLength, boolean done) { 64 | super.onUIFinish(bytesWrite, contentLength, done); 65 | //uploadProgress.setVisibility(View.GONE); //设置进度条不可见 66 | Toast.makeText(getApplicationContext(),"上传成功",Toast.LENGTH_SHORT).show(); 67 | 68 | } 69 | }; 70 | 71 | 72 | //开始Post请求,上传文件 73 | OKHttpUtils.doPostRequest(POST_FILE_URL, initUploadFile(), uiProgressRequestListener, new Callback() { 74 | @Override 75 | public void onFailure(Call call, final IOException e) { 76 | Log.i("TAG", "error------> "+e.getMessage()); 77 | runOnUiThread(new Runnable() { 78 | @Override 79 | public void run() { 80 | Toast.makeText(MainActivity.this, "上传失败"+e.getMessage(), Toast.LENGTH_SHORT).show(); 81 | } 82 | }); 83 | 84 | } 85 | 86 | @Override 87 | public void onResponse(Call call, Response response) throws IOException { 88 | Log.i("TAG", "success---->"+response.body().string()); 89 | } 90 | }); 91 | 92 | } 93 | 94 | //初始化上传文件的数据 95 | private List initUploadFile(){ 96 | List fileNames = new ArrayList<>(); 97 | fileNames.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) 98 | + File.separator + "test.txt"); //txt文件 99 | fileNames.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) 100 | + File.separator + "bell.png"); //图片 101 | fileNames.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) 102 | + File.separator + "kobe.mp4"); //视频 103 | fileNames.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) 104 | + File.separator + "xinnian.mp3"); //音乐 105 | return fileNames; 106 | } 107 | 108 | ``` 109 | 110 | **3、文件下载的调用** 111 | ``` 112 | //文件下载 113 | private void download() { 114 | //这个是非ui线程回调,不可直接操作UI 115 | final ProgressListener progressResponseListener = new ProgressListener() { 116 | @Override 117 | public void onProgress(long bytesRead, long contentLength, boolean done) { 118 | Log.i("TAG", "bytesRead:" + bytesRead); 119 | Log.i("TAG", "contentLength:" + contentLength); 120 | Log.i("TAG", "done:" + done); 121 | if (contentLength != -1) { 122 | //长度未知的情况下回返回-1 123 | Log.i("TAG", (100 * bytesRead) / contentLength + "% done"); 124 | } 125 | Log.i("TAG", "================================"); 126 | } 127 | }; 128 | 129 | 130 | //这个是ui线程回调,可直接操作UI 131 | final UIProgressListener uiProgressResponseListener = new UIProgressListener() { 132 | @Override 133 | public void onUIProgress(long bytesRead, long contentLength, boolean done) { 134 | Log.i("TAG", "bytesRead:" + bytesRead); 135 | Log.i("TAG", "contentLength:" + contentLength); 136 | Log.i("TAG", "done:" + done); 137 | if (contentLength != -1) { 138 | //长度未知的情况下回返回-1 139 | Log.i("TAG", (100 * bytesRead) / contentLength + "% done"); 140 | } 141 | Log.i("TAG", "================================"); 142 | //ui层回调,设置下载进度 143 | int progress = (int) ((100 * bytesRead) / contentLength); 144 | downloadProgress.setProgress(progress); 145 | downloadTv.setText("下载进度:" + progress +"%"); 146 | } 147 | 148 | @Override 149 | public void onUIStart(long bytesRead, long contentLength, boolean done) { 150 | super.onUIStart(bytesRead, contentLength, done); 151 | Toast.makeText(getApplicationContext(),"开始下载",Toast.LENGTH_SHORT).show(); 152 | } 153 | 154 | @Override 155 | public void onUIFinish(long bytesRead, long contentLength, boolean done) { 156 | super.onUIFinish(bytesRead, contentLength, done); 157 | Toast.makeText(getApplicationContext(),"下载完成",Toast.LENGTH_SHORT).show(); 158 | } 159 | }; 160 | 161 | //开启文件下载 162 | OKHttpUtils.downloadAndSaveFile(this,DOWNLOAD_TEST_URL,STORE_DOWNLOAD_FILE_PATH,uiProgressResponseListener); 163 | 164 | } 165 | ``` 166 | 167 | **备注** 168 | > 文件上传、下载中的UIProgressListener 实现的3个方法onUIProgress()、onUIStart()、onUIFinish()的内容都可以根据项目需求自定义 169 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "24.0.3" 6 | defaultConfig { 7 | applicationId "com.zx.okhttp3" 8 | minSdkVersion 17 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:24.2.1' 28 | testCompile 'junit:junit:4.12' 29 | compile 'com.squareup.okhttp3:okhttp:3.5.0' 30 | compile 'com.google.code.gson:gson:2.8.0' 31 | compile project(':library') 32 | } 33 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\SDK\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/zx/okhttp3/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.zx.okhttp3; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.zx.okhttp3", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/zx/okhttp3/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zx.okhttp3; 2 | 3 | import android.os.Bundle; 4 | import android.os.Environment; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.ProgressBar; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import com.zx.uploadlibrary.listener.ProgressListener; 13 | import com.zx.uploadlibrary.listener.impl.UIProgressListener; 14 | import com.zx.uploadlibrary.utils.OKHttpUtils; 15 | 16 | import java.io.File; 17 | import java.io.IOException; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import okhttp3.Call; 22 | import okhttp3.Callback; 23 | import okhttp3.Response; 24 | 25 | public class MainActivity extends AppCompatActivity{ 26 | 27 | 28 | 29 | //上传文件到服务器的地址(使用的时候替换成自己的服务器地址) 30 | private static final String POST_FILE_URL = "http://192.168.1.3:8080/UploadFileDemo/MutilUploadServlet"; 31 | //下载文件的地址 32 | private static final String DOWNLOAD_TEST_URL = "http://oh0vbg8a6.bkt.clouddn.com/app-debug.apk"; 33 | 34 | //下载的文件的存储路径 35 | private static final String STORE_DOWNLOAD_FILE_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator +"download2.apk"; 36 | private ProgressBar uploadProgress, downloadProgress; 37 | private TextView uploadTV,downloadTv; 38 | 39 | 40 | 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | setContentView(R.layout.activity_main); 45 | initView(); 46 | } 47 | 48 | //初始化View 49 | private void initView() { 50 | uploadProgress = (ProgressBar) findViewById(R.id.upload_progress); 51 | downloadProgress = (ProgressBar) findViewById(R.id.download_progress); 52 | uploadTV = (TextView) findViewById(R.id.tv_upload_progress); 53 | downloadTv = (TextView) findViewById(R.id.tv_download_progress); 54 | findViewById(R.id.upload).setOnClickListener(new View.OnClickListener() { 55 | @Override 56 | public void onClick(View v) { 57 | upload(); 58 | } 59 | }); 60 | findViewById(R.id.download).setOnClickListener(new View.OnClickListener() { 61 | @Override 62 | public void onClick(View v) { 63 | download(); 64 | } 65 | }); 66 | } 67 | 68 | //多文件上传(带进度) 69 | private void upload() { 70 | //这个是非ui线程回调,不可直接操作UI 71 | final ProgressListener progressListener = new ProgressListener() { 72 | @Override 73 | public void onProgress(long bytesWrite, long contentLength, boolean done) { 74 | Log.i("TAG", "bytesWrite:" + bytesWrite); 75 | Log.i("TAG", "contentLength" + contentLength); 76 | Log.i("TAG", (100 * bytesWrite) / contentLength + " % done "); 77 | Log.i("TAG", "done:" + done); 78 | Log.i("TAG", "================================"); 79 | } 80 | }; 81 | 82 | 83 | //这个是ui线程回调,可直接操作UI 84 | UIProgressListener uiProgressRequestListener = new UIProgressListener() { 85 | @Override 86 | public void onUIProgress(long bytesWrite, long contentLength, boolean done) { 87 | Log.i("TAG", "bytesWrite:" + bytesWrite); 88 | Log.i("TAG", "contentLength" + contentLength); 89 | Log.i("TAG", (100 * bytesWrite) / contentLength + " % done "); 90 | Log.i("TAG", "done:" + done); 91 | Log.i("TAG", "================================"); 92 | //ui层回调,设置当前上传的进度值 93 | int progress = (int) ((100 * bytesWrite) / contentLength); 94 | uploadProgress.setProgress(progress); 95 | uploadTV.setText("上传进度值:" + progress + "%"); 96 | } 97 | 98 | //上传开始 99 | @Override 100 | public void onUIStart(long bytesWrite, long contentLength, boolean done) { 101 | super.onUIStart(bytesWrite, contentLength, done); 102 | Toast.makeText(getApplicationContext(),"开始上传",Toast.LENGTH_SHORT).show(); 103 | } 104 | 105 | //上传结束 106 | @Override 107 | public void onUIFinish(long bytesWrite, long contentLength, boolean done) { 108 | super.onUIFinish(bytesWrite, contentLength, done); 109 | //uploadProgress.setVisibility(View.GONE); //设置进度条不可见 110 | Toast.makeText(getApplicationContext(),"上传成功",Toast.LENGTH_SHORT).show(); 111 | 112 | } 113 | }; 114 | 115 | 116 | //开始Post请求,上传文件 117 | OKHttpUtils.doPostRequest(POST_FILE_URL, initUploadFile(), uiProgressRequestListener, new Callback() { 118 | @Override 119 | public void onFailure(Call call, final IOException e) { 120 | Log.i("TAG", "error------> "+e.getMessage()); 121 | runOnUiThread(new Runnable() { 122 | @Override 123 | public void run() { 124 | Toast.makeText(MainActivity.this, "上传失败"+e.getMessage(), Toast.LENGTH_SHORT).show(); 125 | } 126 | }); 127 | 128 | } 129 | 130 | @Override 131 | public void onResponse(Call call, Response response) throws IOException { 132 | Log.i("TAG", "success---->"+response.body().string()); 133 | } 134 | }); 135 | 136 | } 137 | 138 | 139 | //文件下载 140 | private void download() { 141 | //这个是非ui线程回调,不可直接操作UI 142 | final ProgressListener progressResponseListener = new ProgressListener() { 143 | @Override 144 | public void onProgress(long bytesRead, long contentLength, boolean done) { 145 | Log.i("TAG", "bytesRead:" + bytesRead); 146 | Log.i("TAG", "contentLength:" + contentLength); 147 | Log.i("TAG", "done:" + done); 148 | if (contentLength != -1) { 149 | //长度未知的情况下回返回-1 150 | Log.i("TAG", (100 * bytesRead) / contentLength + "% done"); 151 | } 152 | Log.i("TAG", "================================"); 153 | } 154 | }; 155 | 156 | 157 | //这个是ui线程回调,可直接操作UI 158 | final UIProgressListener uiProgressResponseListener = new UIProgressListener() { 159 | @Override 160 | public void onUIProgress(long bytesRead, long contentLength, boolean done) { 161 | Log.i("TAG", "bytesRead:" + bytesRead); 162 | Log.i("TAG", "contentLength:" + contentLength); 163 | Log.i("TAG", "done:" + done); 164 | if (contentLength != -1) { 165 | //长度未知的情况下回返回-1 166 | Log.i("TAG", (100 * bytesRead) / contentLength + "% done"); 167 | } 168 | Log.i("TAG", "================================"); 169 | //ui层回调,设置下载进度 170 | int progress = (int) ((100 * bytesRead) / contentLength); 171 | downloadProgress.setProgress(progress); 172 | downloadTv.setText("下载进度:" + progress +"%"); 173 | } 174 | 175 | @Override 176 | public void onUIStart(long bytesRead, long contentLength, boolean done) { 177 | super.onUIStart(bytesRead, contentLength, done); 178 | Toast.makeText(getApplicationContext(),"开始下载",Toast.LENGTH_SHORT).show(); 179 | } 180 | 181 | @Override 182 | public void onUIFinish(long bytesRead, long contentLength, boolean done) { 183 | super.onUIFinish(bytesRead, contentLength, done); 184 | Toast.makeText(getApplicationContext(),"下载完成",Toast.LENGTH_SHORT).show(); 185 | } 186 | }; 187 | 188 | //开启文件下载 189 | OKHttpUtils.downloadAndSaveFile(this,DOWNLOAD_TEST_URL,STORE_DOWNLOAD_FILE_PATH,uiProgressResponseListener); 190 | 191 | } 192 | 193 | //初始化上传文件的数据 194 | private List initUploadFile(){ 195 | List fileNames = new ArrayList<>(); 196 | fileNames.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) 197 | + File.separator + "test.txt"); //txt文件 198 | fileNames.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) 199 | + File.separator + "bell.png"); //图片 200 | fileNames.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) 201 | + File.separator + "kobe.mp4"); //视频 202 | fileNames.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) 203 | + File.separator + "xinnian.mp3"); //音乐 204 | return fileNames; 205 | } 206 | 207 | } 208 | -------------------------------------------------------------------------------- /app/src/main/java/com/zx/okhttp3/OKHttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.zx.okhttp3; 2 | 3 | 4 | import com.zx.uploadlibrary.helper.ProgressHelper; 5 | import com.zx.uploadlibrary.listener.ProgressListener; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.net.FileNameMap; 10 | import java.net.URLConnection; 11 | import java.util.List; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import okhttp3.Call; 15 | import okhttp3.Callback; 16 | import okhttp3.MediaType; 17 | import okhttp3.MultipartBody; 18 | import okhttp3.OkHttpClient; 19 | import okhttp3.Request; 20 | import okhttp3.RequestBody; 21 | import okhttp3.Response; 22 | 23 | /** 24 | * Created by 周旭 on 2017/1/18. 25 | * OKHttp工具类(上传,下载文件) 26 | */ 27 | 28 | public class OKHttpUtils { 29 | 30 | private static OkHttpClient client; 31 | 32 | /** 33 | * 创建一个OkHttpClient的对象的单例 34 | * @return 35 | */ 36 | private synchronized static OkHttpClient getOkHttpClientInstance() { 37 | if (client == null) { 38 | OkHttpClient.Builder builder = new OkHttpClient.Builder() 39 | //设置连接超时等属性,不设置可能会报异常 40 | .connectTimeout(120, TimeUnit.SECONDS) 41 | .readTimeout(120, TimeUnit.SECONDS) 42 | .writeTimeout(120, TimeUnit.SECONDS); 43 | 44 | client = builder.build(); 45 | } 46 | return client; 47 | } 48 | 49 | 50 | /** 51 | * 获取文件MimeType 52 | * 53 | * @param filename 54 | * @return 55 | */ 56 | private static String getMimeType(String filename) { 57 | FileNameMap filenameMap = URLConnection.getFileNameMap(); 58 | String contentType = filenameMap.getContentTypeFor(filename); 59 | if (contentType == null) { 60 | contentType = "application/octet-stream"; //* exe,所有的可执行程序 61 | } 62 | return contentType; 63 | } 64 | 65 | 66 | /** 67 | * 获得Request实例(不带进度) 68 | * @param url 69 | * @return 70 | */ 71 | private static Request getRequest(String url, List fileNames) { 72 | Request.Builder builder = new Request.Builder(); 73 | builder.url(url) 74 | .post(getRequestBody(fileNames)); 75 | return builder.build(); 76 | } 77 | 78 | 79 | /** 80 | * 获得Request实例(带进度) 81 | * @param url 82 | * @return 83 | */ 84 | private static Request getRequest(String url, List fileNames, ProgressListener uiProgressRequestListener) { 85 | Request.Builder builder = new Request.Builder(); 86 | builder.url(url) 87 | .post(ProgressHelper.addProgressRequestListener( 88 | OKHttpUtils.getRequestBody(fileNames), 89 | uiProgressRequestListener)); 90 | return builder.build(); 91 | } 92 | 93 | 94 | /** 95 | * 通过上传的文件的完整路径生成RequestBody 96 | * @param fileNames 完整的文件路径 97 | * @return 98 | */ 99 | private static RequestBody getRequestBody(List fileNames) { 100 | //创建MultipartBody.Builder,用于添加请求的数据 101 | MultipartBody.Builder builder = new MultipartBody.Builder(); 102 | for (int i = 0; i < fileNames.size(); i++) { //对文件进行遍历 103 | File file = new File(fileNames.get(i)); //生成文件 104 | //根据文件的后缀名,获得文件类型 105 | String fileType = getMimeType(file.getName()); 106 | builder.addFormDataPart( //给Builder添加上传的文件 107 | "image", //请求的名字 108 | file.getName(), //文件的文字,服务器端用来解析的 109 | RequestBody.create(MediaType.parse(fileType), file) //创建RequestBody,把上传的文件放入 110 | ); 111 | } 112 | return builder.build(); //根据Builder创建请求 113 | } 114 | 115 | /** 116 | * 根据url,发送异步Post请求(带进度) 117 | * @param url 提交到服务器的地址 118 | * @param fileNames 完整的上传的文件的路径名 119 | * @param callback OkHttp的回调接口 120 | */ 121 | public static void doPostRequest(String url, List fileNames, ProgressListener uiProgressRequestListener, Callback callback) { 122 | Call call = getOkHttpClientInstance().newCall(getRequest(url,fileNames,uiProgressRequestListener)); 123 | call.enqueue(callback); 124 | } 125 | 126 | /** 127 | * 根据url,发送异步Post请求(不带进度) 128 | * @param url 提交到服务器的地址 129 | * @param fileNames 完整的上传的文件的路径名 130 | * @param callback OkHttp的回调接口 131 | */ 132 | public static void doPostRequest(String url, List fileNames, Callback callback) { 133 | Call call = getOkHttpClientInstance().newCall(getRequest(url,fileNames)); 134 | call.enqueue(callback); 135 | } 136 | 137 | //获取字符串 138 | public static String getString(Response response) throws IOException { 139 | if (response != null && response.isSuccessful()) { 140 | return response.body().string(); 141 | } 142 | return null; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 25 | 26 |