Step1:整体过程
/**
* 由于请求框架开始就是Xutils compile ‘org.xutils:xutils:3.3.36’ 不做更改
* 1.第三方的图片选择器(支持选择多张图片、预览、删除等)
* 2.onActivityResult 返回选择图片的数组
* 3.注意:接口有2个 A接口:专门用于接受图片base64码 B接口用来上传 标题、内容和拼接的url链接
* 4.
* ①:将选取的图片路径的转化为base64字符串 encode()方法
* ②:选取多张时采用计数叠加一张张的上传 每上传一张将地址进行拼接 StringBuffer()方法
* ③:当上传图片完成时A接口结束,在调用B接口 传入对应的参数即可,图片是多张之后的url链接,要去除第一个,号否则后台解析失败 substring()方法
*/
上图中一共上传了9张图片,蓝色部分就是一至9张的叠加链接,一共花了9秒 当然这些图片都是很小的,如果是高清图 记着一定要压缩 否则会非常慢,因为流程非常多,容易卡死
Step3:进入主题
build.gradle 引入这些
1
2
3
4
5
6
7
8
9
10
11
12
//recyclerview 展示图片的
compile 'com.android.support:recyclerview-v7:25.3.1'
//请求网络框架xutils
compile 'org.xutils:xutils:3.3.36'
//加载图片的glide
compile 'com.github.bumptech.glide:glide:3.7.0'
//图库选择器
compile 'me.iwf.photopicker:PhotoPicker:0.9.5@aar'
//压缩图片的
compile 'com.zxy.android:tiny:0.0.6'
//删除图片显示的snackbar
compile 'com.android.support:design:26.0.0-alpha1
Step4:AndroidManifest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.helloworld.base64demo"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".AppContext"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- photopicker图片选取界面 -->
<activity
android:name="me.iwf.photopicker.PhotoPickerActivity"
android:theme="@style/Theme.AppCompat.NoActionBar" />
<!-- photopicker选取图片预览删除界面 -->
<activity
android:name="me.iwf.photopicker.PhotoPagerActivity"
android:theme="@style/Theme.AppCompat.NoActionBar" />
</application>
</manifest>
Step5:4个java类
1.AppContext
2.MainActivity
3.PhotoAdapter
4.RecyclerItemClickListener
1.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.helloworld.base64demo;
import android.app.Application;
import com.zxy.tiny.Tiny;
import org.xutils.x;
public class AppContext extends Application {
public static AppContext mInstace;
@Override
public void onCreate() {
super.onCreate();
/**
* 初始化第三方库
*/
x.Ext.init(this);
mInstace = this;
/**
* 压缩的
*/
Tiny.getInstance().getApplication();
}
}
2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
package com.helloworld.base64demo;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.zxy.tiny.Tiny;
import com.zxy.tiny.callback.BitmapCallback;
import org.json.JSONException;
import org.json.JSONObject;
import org.xutils.common.Callback;
import org.xutils.http.RequestParams;
import org.xutils.x;
import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import me.iwf.photopicker.PhotoPicker;
import me.iwf.photopicker.PhotoPreview;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private PhotoAdapter photoAdapter;
private ArrayList<String> selectedPhotos = new ArrayList<>();
//原生进度框
private ProgressDialog progressdialog;
private static final String TAG = "ReleaseActivity";
/**
* 图片路径
*/
private List<String> photos;
//发布标题、内容接口 (这里的链接换上自己服务器上的)
private static final String URL = "http://110.110.110.10:8080/api/information/publicInformation";
//上传图片的接口 专门接受base64吗
private static final String URLIMAGE = "http://110.110.110.10:8080/api/information/uploadImage";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) this.findViewById(R.id.recyclerView);
progressdialog = new ProgressDialog(this);
progressdialog.setMessage("正在上传,请稍后...");
//发布按钮事件
TextView release_submit = (TextView) this.findViewById(R.id.release_submit);
release_submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//点击后显示弹框
progressdialog.show();
UploadImageBase64();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss ");
Date curDate = new Date(System.currentTimeMillis());//获取当前时间
String str = formatter.format(curDate);
Log.e(TAG, "UploadImageBase6开始时间: " + str);
}
});
initview();
}
private void initview() {
photoAdapter = new PhotoAdapter(this, selectedPhotos);
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, OrientationHelper.VERTICAL));
recyclerView.setAdapter(photoAdapter);
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, new RecyclerItemClickListener
.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
if (photoAdapter.getItemViewType(position) == PhotoAdapter.TYPE_ADD) {
PhotoPicker.builder()
.setPhotoCount(9) //可选择的图片数
.setShowCamera(true)//是否打开相机
.setPreviewEnabled(false)
.setSelected(selectedPhotos)//选择过的图片出来在进入,默认打上勾
.start(MainActivity.this);
} else {
PhotoPreview.builder()
.setPhotos(selectedPhotos)
.setCurrentItem(position)
.start(MainActivity.this);
}
}
}));
}
/**
* 选择了图片
*/
private String str;
private void UploadImageBase64() {
//当number大于或等于图片组大小时结束,并return
if (number >= photos.size()) {
//代表图片上传完毕,开始发布
if (photos.size() > 1) {
//图片大于1张时去除第一个,
str = String.valueOf(sb).substring(1, sb.length());
} else {
str = String.valueOf(sb);
}
//请求的链接、谁发布的(一般为uid)、发布的标题、发布的内容、最后拼接的图片链接
testUploadFile(URL, "1", "123", "456", str);
//打印 最后拼接的图片链接
Log.e(TAG, "UploadImageBase64图片: " + str);
return;
}
//随便找的压缩方法 可以自己写在工具类里 不建议用第三方的
Tiny.BitmapCompressOptions options = new Tiny.BitmapCompressOptions();
Tiny.getInstance().source(photos.get(number)).asBitmap().withOptions(options).compress(new BitmapCallback() {
@Override
public void callback(boolean isSuccess, Bitmap bitmap) {
//A接口 请求专门上传图片的链接、每次转换时的base64字符串、
// 这里的2只是区别是头像上传还是朋友圈上传 可去除该参数
UploadFile(URLIMAGE, "1", encode(photos.get(number)), "2");
//打印 每张图片的base64码
Log.e(TAG, "callback: 压缩方法" + encode(photos.get(number)));
}
});
}
/**
* 方法1
*/
private String encode(String path) {
Bitmap bitmap = BitmapFactory.decodeFile(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] bytes = baos.toByteArray();
//这里有4种模式 defalut 是不连续的 me后台接不到
//NO_WRAP 是连续的 还有2种在这就不做解释了
byte[] encode = Base64.encode(bytes, Base64.NO_WRAP);
String encodeString = new String(encode);
return encodeString;
}
//msg 请求的结果
private String msg;
/**
* 图片上传
*/
private void testUploadFile(String url, String userId, String title, String content, String icons) {
//4个对应的参数 用户id、标题、内容、拼接的图片地址
RequestParams params = new RequestParams(url);
params.addBodyParameter("userId", userId);
params.addBodyParameter("title", title);
params.addBodyParameter("content", content);
params.addBodyParameter("icons", icons);
x.http().post(params, new Callback.CacheCallback<String>() {
@Override
public void onSuccess(String result) {
try {
JSONObject object = new JSONObject(result);
//返回状态
String status = object.optString("status");
//返回的消息
msg = object.optString("msg");
//成功关闭进度框
progressdialog.dismiss();
//200 说明成功
if (status.equals("200")) {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
//记录从点击到结束的所花时间 (可删除)
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss ");
Date curDate = new Date(System.currentTimeMillis());//获取当前时间
String str = formatter.format(curDate);
Log.e(TAG, "UploadImageBase6结束时间: " + str);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
//失败也要关闭对话框
progressdialog.dismiss();
Log.e(TAG, "onError: ");
}
@Override
public void onCancelled(CancelledException cex) {
Log.e(TAG, "onCancelled: ");
}
@Override
public void onFinished() {
Log.e(TAG, "onFinished456: " + msg);
}
@Override
public boolean onCache(String result) {
Log.e(TAG, "onCache: ");
return false;
}
});
}
/**
* 图片上传
* 地址,图片集、图片名称、type(默认为2)
*/
private int number = 0;
private String status, data;
private StringBuffer sb = new StringBuffer();
private void UploadFile(String url, String userId, String icon, String type) {
//专门接收base64 的接口 用户id、图片、type与上面一致 只是为了区别(可删除)
RequestParams params = new RequestParams(url);
params.addBodyParameter("userId", userId);
params.addBodyParameter("icon", icon);
params.addBodyParameter("type", type);
x.http().post(params, new Callback.CacheCallback<String>() {
@Override
public void onSuccess(String result) {
try {
JSONObject object = new JSONObject(result);
status = object.optString("status");
data = object.optString("data");
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
Log.e(TAG, "onError: " + status);
}
@Override
public void onCancelled(CancelledException cex) {
Log.e(TAG, "onCancelled: ");
}
@Override
public void onFinished() {
//说明上传成功
if (status.equals("200")) {
//当图片大于1张是,进行分隔
if (photos.size() > 1) {
sb.append("," + data);
} else {
//等于一张时不用
sb.append(data);
}
//每上传完一张递增加1
number++;
//在此调取上传图片接口
UploadImageBase64();
}
Log.e(TAG, "onFinished: " + photos.size() + "n" + sb);
}
@Override
public boolean onCache(String result) {
Log.e(TAG, "onCache: ");
return false;
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && (requestCode == PhotoPicker.REQUEST_CODE ||
requestCode == PhotoPreview.REQUEST_CODE)) {
photos = null;
if (data != null) {
//获取图片的list
photos = data.getStringArrayListExtra(PhotoPicker.KEY_SELECTED_PHOTOS);
}
//清除list
selectedPhotos.clear();
if (photos != null) {
//添加至list中
selectedPhotos.addAll(photos);
}
//刷新适配器
photoAdapter.notifyDataSetChanged();
}
}
}
3.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package com.helloworld.base64demo;
import android.content.Context;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import java.io.File;
import java.util.ArrayList;
import me.iwf.photopicker.utils.AndroidLifecycleUtils;
public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHolder> {
private ArrayList<String> photoPaths = new ArrayList<String>();
private LayoutInflater inflater;
private Context mContext;
public final static int TYPE_ADD = 1;
public final static int TYPE_PHOTO = 2;
final static int MAX = 9;
public PhotoAdapter(Context mContext, ArrayList<String> photoPaths) {
this.photoPaths = photoPaths;
this.mContext = mContext;
inflater = LayoutInflater.from(mContext);
}
@Override
public PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = null;
switch (viewType) {
case TYPE_ADD:
itemView = inflater.inflate(R.layout.item_add, parent, false);
break;
case TYPE_PHOTO:
//包里面的
itemView = inflater.inflate(R.layout.__picker_item_photo, parent, false);
break;
}
return new PhotoViewHolder(itemView);
}
@Override
public void onBindViewHolder(final PhotoViewHolder holder, final int position) {
if (getItemViewType(position) == TYPE_PHOTO) {
Uri uri = Uri.fromFile(new File(photoPaths.get(position)));
boolean canLoadImage = AndroidLifecycleUtils.canLoadImage(holder.ivPhoto.getContext());
if (canLoadImage) {
Glide.with(mContext)
.load(uri)
.centerCrop()
.thumbnail(0.1f)
.placeholder(R.drawable.__picker_ic_photo_black_48dp)
.error(R.drawable.__picker_ic_broken_image_black_48dp)
.into(holder.ivPhoto);
}
}
}
@Override
public int getItemCount() {
int count = photoPaths.size() + 1;
if (count > MAX) {
count = MAX;
}
return count;
}
@Override
public int getItemViewType(int position) {
return (position == photoPaths.size() && position != MAX) ? TYPE_ADD : TYPE_PHOTO;
}
public static class PhotoViewHolder extends RecyclerView.ViewHolder {
private ImageView ivPhoto;
private View vSelected;
public PhotoViewHolder(View itemView) {
super(itemView);
ivPhoto = (ImageView) itemView.findViewById(R.id.iv_photo);
vSelected = itemView.findViewById(R.id.v_selected);
if (vSelected != null) vSelected.setVisibility(View.GONE);
}
}
}
4.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.helloworld.base64demo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
/**
* 点击事件 删除
*/
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildLayoutPosition(childView));
return true;
}
return false;
}
@Override public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
step6: 2个布局
1.activity_main.xml
2.item_add.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"
android:paddingBottom="12dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:paddingTop="12dp"/>
<TextView
android:id="@+id/release_submit"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginBottom="70dp"
android:layout_marginLeft="22dp"
android:layout_marginRight="22dp"
android:layout_marginTop="70dp"
android:background="#666"
android:gravity="center"
android:text="发布"
android:textColor="#fff"/>
</LinearLayout>
2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<me.iwf.photopicker.widget.SquareItemLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:background="@drawable/xinxi_tupian"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</me.iwf.photopicker.widget.SquareItemLayout>
Step7:结束
最后
以上就是鲜艳电脑最近收集整理的关于安卓Base64批量上传至服务器的全部内容,更多相关安卓Base64批量上传至服务器内容请搜索靠谱客的其他文章。
发表评论 取消回复