安卓Base64批量上传至服务器

来源:互联网 发布:西装 知乎 编辑:程序博客网 时间:2024/06/06 08:42

Step1:效果图
这里写图片描述

这里写图片描述

Step2:整体过程

/**
* 由于请求框架开始就是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:结束

原创粉丝点击