概述
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 引入这些
//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
<?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.
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.
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.
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.
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
<?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.
<?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批量上传至服务器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复