oss图片上传android_android oss上传图片 - CSDN
  • 本篇博客主要介绍的是将本地图片上传到服务器的方法技巧。主要技术点是: 一、运用第三方可以从相册中选取多张图片。 二、将图片进行压缩处理。 三、上传到阿里云OSS。技术相对简单,主要是将这些技术结合起来的...

        在开发APP软件中,boss突然提出想在软件中添加一个多张照片上传的功能,作为菜鸟的我,琢磨了两天,才弄出来,今天特地贴出来。本篇博客主要介绍的是将本地图片上传到服务器的方法技巧。主要技术点是:
    一、运用第三方可以从相册中选取多张图片。
    二、将图片进行压缩处理。
    三、上传到阿里云OSS。

    技术相对简单,主要是将这些技术结合起来的例子并不多,而且阿里云OSS的资料也不是很丰富,开发文档也是很简略,因此趁此机会将我的思路共享出来。

    PS:请先配置好应用权限。另外,这是公司项目的一个功能,有些地方只好删除,可能看着不是很完整,有时间我再自己做个Demo共享一下。

    一、图片选择

    android机型几乎每个品牌都有自己的相册,因此为了兼容性,自定义一个图库是比较好的办法,而且这次开发要求选取多张图片,使用自定义的开来也是最佳方案,当然为了开发的简便性,我直接使用的第三方,如果需要自定义的,可以参考下鸿洋大神的博客。
    Android 超高仿微信图片选择器 图片该这么加载
    不过目前,支持多图选择的第三方控件也是挺多的,比如MultiImageSelector、MultipleImagePick、PhotoPicker、GalleryPick等等,我大致看了下,使用方法是大同小异的。这次开发中,我们使用的是GalleryPick,基本使用方法可以看看github的介绍。GalleryPick地址
    这里几乎就没什么好介绍了,需要的注意的地方,YangcyYe也介绍的很详细。代码:

            ImageConfig imageConfig
                            = new ImageConfig.Builder(
                            // GlideLoader 可用自己用的缓存库
                            new GlideLoader())
                            // 如果在 4.4 以上,则修改状态栏颜色 (默认黑色)
                            .steepToolBarColor(getResources().getColor(R.color.blue))
                            // 标题的背景颜色 (默认黑色)
                            .titleBgColor(getResources().getColor(R.color.blue))
                            // 提交按钮字体的颜色  (默认白色)
                            .titleSubmitTextColor(getResources().getColor(R.color.white))
                            // 标题颜色 (默认白色)
                            .titleTextColor(getResources().getColor(R.color.white))
                            // 开启多选   (默认为多选)  (单选 为 singleSelect)
                            .mutiSelect()
                            .crop()
                            // 开启拍照功能 (默认关闭)
                            .showCamera()
                            // 多选时的最大数量   (默认 9 张)
                            .mutiSelectMaxSize(6)
                            // 已选择的图片路径
                            .pathList(path)
                            // 拍照后存放的图片路径(默认 /temp/picture)
                            .filePath("/ImageSelector/Pictures")
                            .requestCode(REQUEST_CODE)
                            .build();
    
    
                    ImageSelector.open(OrderDetailActivity.this, imageConfig);   // 开启图片选择器

    图片选择后是在onActivityResult函数的回调的,和自带的图库是一样的。

    二、图片压缩

    我们公司的项目主要是上传手机拍的照片,现在的手机像素都是极高的,一不小心就是OOM,更重要的是在天朝流量是“奢侈品”,让用户一不小心就是十几M的流量没了,这也是不行的,所以上传前必须对照片进行压缩优化。

    网上相关介绍也是颇多,我直接贴代码,各位看看,应该是挺好理解的。

    public class BitmapUtils {
    
        //压缩图片尺寸
        public static Bitmap compressBySize(String pathName, int targetWidth,
                                     int targetHeight) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            opts.inJustDecodeBounds = true;// 不去真的解析图片,只是获取图片的头部信息,包含宽高等;
            Bitmap bitmap = BitmapFactory.decodeFile(pathName, options);
    
            // 得到图片的宽度、高度;
            float imgWidth = options.outWidth;
            float imgHeight = options.outHeight;
    
            // 分别计算图片宽度、高度与目标宽度、高度的比例;取大于等于该比例的最小整数;
            int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);
            int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);
            options.inSampleSize = 1;
    
            // 如果尺寸接近则不压缩,否则进行比例压缩
            if (widthRatio > 1 || widthRatio > 1) {
                if (widthRatio > heightRatio) {
                    options.inSampleSize = widthRatio;
                } else {
                    options.inSampleSize = heightRatio;
                }
            }
    
            //设置好缩放比例后,加载图片进内容;
            options.inJustDecodeBounds = false; // 这里一定要设置false
            bitmap = BitmapFactory.decodeFile(pathName, opts);
            return bitmap;
        }
    }

    一般而言,大小保持在720P左右即可,至少我是这么设置的。压缩的图片,可以通过适配器实现QQ控件图片上传时展现的效果。代码:

        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
        recycler.setLayoutManager(gridLayoutManager);
        adapter = new Adapter(this, path);
        recycler.setAdapter(adapter);

    其适配器的完整代码

     public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
    
        private Context context;
        private LayoutInflater mLayoutInflater;
        private List<String> result;
        private final static String TAG = "Adapter";
    
        public Adapter(Context context, List<String> result) {
            mLayoutInflater = LayoutInflater.from(context);
            this.context = context;
            this.result = result;
        }
    
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ViewHolder(mLayoutInflater.inflate(R.layout.image, null));
        }
    
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            Glide.with(context)
                    .load(result.get(position))
                    .centerCrop()
                    .into(holder.image);
    
        }
    
        @Override
        public int getItemCount() {
            return result.size();
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder {
    
            ImageView image;
    
            public ViewHolder(View itemView) {
                super(itemView);
                image = (ImageView) itemView.findViewById(R.id.image);
            }
    
        }
    }

    图片如此处理就可以了,但我们公司使用的是阿里云Oss,因此,我把处理过的文件又重新保存到sd里面去了。也把代码贴出来吧:

            long time = System.currentTimeMillis();
            String t = new SimpleDateFormat("yyyy_MM_dd").format(new Date(time));
            String d = new SimpleDateFormat("HH_mm").format(new Date(time));
    
            // 压缩图片保存的目录路径
            String filePath = MyApplication.getTruename() + "/" + t + "/" + d;
    
            // 压缩后图片保存的文件名
            String fileName = "photo" + "(" + number + ")" + ".jpg";
    
            File file = new File(getSDPath() + "/" + "myApp" + "/" + filePath);
            File dir = new File(file, fileName);//将要保存图片的路径,android推荐这种写法,将目录名和文件名分开,不然容易报错。
    
            try {
                //压缩图片
                Bitmap bitmap = BitmapUtils.compressBySize(srcPath, 1280, 768);
                if (!file.exists()) {
                    file.mkdirs();
                }
                if (!dir.exists()) {
                    try {
                        dir.createNewFile();
                        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dir));
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 30, bos);
                    bos.flush();
                    bos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    
            } catch (Exception e) {
                e.printStackTrace();
            } 

    getSdPath就是获取SD的路径,代码如下:

        public static String getSDPath() {
            File sdDir = null;
            boolean sdCardExist = Environment.getExternalStorageState()
                    .equals(android.os.Environment.MEDIA_MOUNTED);//判断sd卡是否存在
            if (sdCardExist) {
                sdDir = Environment.getExternalStorageDirectory();//获取根目录
            } else {
                getBaseContext().getCacheDir().getAbsolutePath(); // 获取内置内存卡目录
            }
            return sdDir.toString();
        }

    这样基本就完成了图片处理的操作,现在可以开始进行上传操作了。

    三、图片上传

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == REQUEST_CODE && resultCode == RESULT_OK && data != null) {
               // 处理逻辑,requestcode是自己设置和传过来的,RESULT_OK是常量
                path = data.getStringArrayListExtra(ImageSelectorActivity.EXTRA_RESULT);
                // 如果多张图片,可以采取循环上传
                for(String srcPath, path){
                    Log.i("MyTag", srcPath) ;  // 可以看到每张原始图片的地址
                    // 图片处理和保存的逻辑
                    // 图片上传的逻辑,推荐不要放在循环中,多张图片容易造成线程过多
            };
                    initOss(); // 配置OSS 
                    // 第一张图片的上传
                    OssUpload(path.get(0));
        }
     }

    OSS的配置,建议只实例化一次,即不要放在循环体中。

            // ACCESS_ID,ACCESS_KEY是在阿里云申请的
            OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(ACCESS_ID, ACCESS_KEY);
            ClientConfiguration conf = new ClientConfiguration();
            conf.setConnectionTimeout(15 * 1000); // 连接超时,默认15秒
            conf.setSocketTimeout(15 * 1000); // socket超时,默认15秒
            conf.setMaxConcurrentRequest(8); // 最大并发请求数,默认5个
            conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认2次
    
            // oss为全局变量,OSS_ENDPOINT是一个OSS区域地址
            oss = new OSSClient(getApplicationContext(), OSS_ENDPOINT, credentialProvider, conf);

    实例化后,就要将图片上传了,这个逻辑应该在onActivityResult这个方法中执行

    
    public void ossUpload(String strPath){
    
        // 判断图片是否全部上传
        // 如果已经是最后一张图片上传成功,则跳出
        number++;
        if (number == path.size()) {
        // 结束的处理逻辑,并退出该方法
    
            return;
        }
    
        // 指定数据类型,没有指定会自动根据后缀名判断
        ObjectMetadata objectMeta = new ObjectMetadata();
        objectMeta.setContentType("image/jpeg");
    
        // 构造上传请求
        // 这里的objectKey其实就是服务器上的路径,即目录+文件名
        //因为目录命名逻辑涉及公司信息,被我删去,造成不知道这个objectKey不知为何物,如下是我们公司的大致命名逻辑
        //String objectKey = keyPath + "/" + carArr[times] + ".jpg";
        PutObjectRequest put = new PutObjectRequest(BUCKET_NAME, objectKey,dir.getPath());
        put.setMetadata(objectMeta);
        try {
            PutObjectResult putObjectResult = oss.putObject(put);
        } catch (ClientException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }
    
        // 异步上传时可以设置进度回调
        put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
            @Override
            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                // 在这里可以实现进度条展现功能
                Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
            }
       });
        OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
            @Override
            public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                Log.d("PutObject", "UploadSuccess");
                Log.d("ETag", result.getETag());
                Log.d("RequestId", result.getRequestId());
    
                // 这里进行递归单张图片上传,在外面判断是否进行跳出
                if (number <= path.size() - 1) {
                    upOss(path.get(number));
                }
            }
    
            @Override
            public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                // 请求异常
                if (clientExcepion != null) {
                    // 本地异常如网络异常等
                    clientExcepion.printStackTrace();
                }
                if (serviceException != null) {
                    // 服务异常
                    Log.e("ErrorCode", serviceException.getErrorCode());
                    Log.e("RequestId", serviceException.getRequestId());
                    Log.e("HostId", serviceException.getHostId());
                    Log.e("RawMessage", serviceException.getRawMessage());
                }
                ToastUtils.showShort(mContext, "图片上传失败,请重新上传");
                return;
            }
       });
    }

    至此,整个多图上传的过程就完成了,作为菜鸟的我,目前想出来的就是这个笨方法,希望各位大神有更好的方法,不吝赐教!

    2016-10-25 PS:写文章时,只是想将个人想法拿出来探讨,没想到能有这么人评论与浏览,如今看来,这篇博客还存在许多问题,我计划在本周更新本篇博客,以及将demo贴出。

    展开全文
  • android 集成OSS 上传图片
  • 公司的项目需要移动端使用OSS上传图片,对图片进行统一管理,减轻服务端的压力。所以我封装了一个OSS上传图片的工具类,这里做个记录,供自己和其他同仁使用。 首先我们先把库引进来 implementation '...

    公司的项目需要移动端使用OSS上传图片,对图片进行统一管理,减轻服务端的压力。所以我封装了一个OSS上传图片的工具类,这里做个记录,供自己和其他同仁使用。

    首先我们先把库引进来

    implementation 'com.aliyun.dpa:oss-android-sdk:+'

    接着就是我们的工具类接口了

    public interface IOssCallBack {
        public void progress(int progress);//进度回调接口
        public void success();//成功回调接口
        public void failure();//失败回调接口
    }
    

    下来是工具类了

    public class OssUtils {
    
        private static OssUtils ossUtils;
        private static OSS oss;
        private static SharedPreferences sps;
        private static ClientConfiguration conf;
        private static OSSCredentialProvider credetialProvider;
    
        /**
         * 初始化oss对象,这个里面因为有网络请求,需要在我们使用的时候再进行初始化。
         */
        public static OssUtils getInstance(Context context) {
            if (ossUtils == null) {
                ossUtils = new OssUtils();
                //共享参数初始化
                sps = context.getSharedPreferences("clouddriver", Context.MODE_PRIVATE);
                //设置配置文件
                conf = new ClientConfiguration();
                conf.setConnectionTimeout(15 * 1000); // 连接超时,默认15秒。
                conf.setSocketTimeout(15 * 1000); // socket超时,默认15秒。
                conf.setMaxConcurrentRequest(5); // 最大并发请求数,默认5个。
                conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认2次。
            }
            return ossUtils;
        }
    
        /**
         * 单图上传方法
         *
         * @param path
         * @param name
         * @param callBack
         */
        public void uploadPicByPath(Context context, String path, String name, IOssCallBack callBack) {
            if (ossUtils != null) {
                OkGo.get((String) Latte.init().getHash().get(ConfigType.OSS_KEY.name()))
                        .tag(this)
                        .headers("Content-Type", "application/json")
                        .headers("Authorization", "Bearer " + sps.getString("access_token", ""))
                        .params("key", "cloudStsToken")
                        .execute(new MyCallback() {
                            @Override
                            public void onSuccess(String s, Call call, Response response) {
                                OssEntity ossEntity = new Gson().fromJson(s, OssEntity.class);
                                String ak = ossEntity.getData().getAccessKeyId();
                                String sk = ossEntity.getData().getAccessKeySecret();
                                String token = ossEntity.getData().getSecurityToken();
                                String expiration = ossEntity.getData().getExpiration();
                                credetialProvider = new OSSStsTokenCredentialProvider(ak, sk, token);
                                // 配置类如果不设置,会有默认配置。
                                oss = new OSSClient(context, "oss-cn-beijing.aliyuncs.com", credetialProvider, conf);
                                //开始上传工作
                                PutObjectRequest put = new PutObjectRequest("clouds1000", name, path);
                                // 异步上传时可以设置进度回调。
                                put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
                                    @Override
                                    public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                                        callBack.progress((int) (((double) currentSize / (double) totalSize) * 100));
                                    }
                                });
                                OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
                                    @Override
                                    public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                                        callBack.success();
                                    }
    
                                    @Override
                                    public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                                        callBack.failure();
                                    }
                                });
                            }
    
                            @Override
                            public void MyOnError(Call call, Response response, Exception e, String errorMsg) {
                                ToastUtil.showViewToast(context, "请检查您的网络");
                            }
                        });
            }
        }
    
        /**
         * OSS多图上传
         * @param context
         * @param pathList
         */
        public void multiUploadPicByPath(Context context,List<PicUpLoadBean> pathList){
            if (ossUtils != null) {
                OkGo.get((String) Latte.init().getHash().get(ConfigType.OSS_KEY.name()))
                        .tag(this)
                        .headers("Content-Type", "application/json")
                        .headers("Authorization", "Bearer " + sps.getString("access_token", ""))
                        .params("key", "cloudStsToken")
                        .execute(new MyCallback() {
                            @Override
                            public void onSuccess(String s, Call call, Response response) {
                                OssEntity ossEntity = new Gson().fromJson(s, OssEntity.class);
                                String ak = ossEntity.getData().getAccessKeyId();
                                String sk = ossEntity.getData().getAccessKeySecret();
                                String token = ossEntity.getData().getSecurityToken();
                                String expiration = ossEntity.getData().getExpiration();
                                credetialProvider = new OSSStsTokenCredentialProvider(ak, sk, token);
                                // 配置类如果不设置,会有默认配置。
                                oss = new OSSClient(context, "oss-cn-beijing.aliyuncs.com", credetialProvider, conf);
                                //这里开始进行一个循环
                                for (int i=0;i<pathList.size();i++) {
                                    IOssCallBack callBack = pathList.get(i).getCallBack();
                                    String name = pathList.get(i).getPicName();
                                    String path = pathList.get(i).getPicPath();
                                    //开始上传工作
                                    PutObjectRequest put = new PutObjectRequest("clouds1000", name, path);
                                    // 异步上传时可以设置进度回调。
                                    put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
                                        @Override
                                        public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                                            callBack.progress((int) (((double) currentSize / (double) totalSize) * 100));
                                        }
                                    });
                                    OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
                                        @Override
                                        public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                                            callBack.success();
                                        }
    
                                        @Override
                                        public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                                            callBack.failure();
                                        }
                                    });
                                }
                            }
    
                            @Override
                            public void MyOnError(Call call, Response response, Exception e, String errorMsg) {
                                ToastUtil.showViewToast(context, "请检查您的网络");
                            }
                        });
            }
        }
    }

    实体类PicUpLoadBean

    public class PicUpLoadBean {
        private String picName;
        private String picPath;
        private int picProgress;
        private IOssCallBack callBack;
    
        public String getPicName() {
            return picName;
        }
    
        public void setPicName(String picName) {
            this.picName = picName;
        }
    
        public String getPicPath() {
            return picPath;
        }
    
        public void setPicPath(String picPath) {
            this.picPath = picPath;
        }
    
        public int getPicProgress() {
            return picProgress;
        }
    
        public void setPicProgress(int picProgress) {
            this.picProgress = picProgress;
        }
    
        public IOssCallBack getCallBack() {
            return callBack;
        }
    
        public void setCallBack(IOssCallBack callBack) {
            this.callBack = callBack;
        }
    }

    单图上传调用

    String objectName = "android" + sps.getInt("user_id", 0) + System.currentTimeMillis();
    dialogWeb.show();
    OssUtils.getInstance(this).uploadPicByPath(this,UriToPathUtil.getRealFilePath(this, resultUri), objectName, new IOssCallBack() {
        @Override
        public void progress(int progress) {
            Log.i("myoss", progress + "");
        }
    
        @Override
        public void success() {
            dialogWeb.dismiss();
            Log.i("myoss", "success");
        }
    
        @Override
        public void failure() {
            dialogWeb.dismiss();
            Log.i("myoss", "failure");
        }
    });

    多图上传调用

    OssUtils.getInstance(this).multiUploadPicByPath(this,picList);

    这个list的每一个对象对应一个图片,其中包含了图片的ObjectName,路径,上传进度和对应的接口回调,用的时候直接拿出来用就可以了,多张图片不会发生冲突。OSS默认多线程上传。需要注意的一点,这个回调是子线程,如果要更新UI需要配合Handler进行使用。

    展开全文
  • code小生,一个 Android 领域技术分享平台作者:喵主子的阳光...前言 前一阵项目中的上传图片改为上传到阿里上,记录一下实现的过程,方便以后查看。参考资料:官方文档https://link.jianshu.com/?t=https%3A%2F%2Fhelp
        

    code小生,一个 Android 领域技术分享平台

    作者:喵主子的阳光
    链接:https://www.jianshu.com/p/e6da7c5841cf
    声明:本文是 喵主子的阳光 原创,转发等请联系原作者授权。

    前言

    前一阵项目中的上传图片改为上传到阿里上,记录一下实现的过程,方便以后查看。
    参考资料:官方文档

    https://link.jianshu.com/?t=https%3A%2F%2Fhelp.aliyun.com%2Fdocument_detail%2F32047.html%3Fspm%3D5176.doc32047.6.699.0vOwsi

    配置

    Android studio添加依赖

    dependencies {
       compile 'com.aliyun.dpa:oss-android-sdk:2.4.5'
       compile 'com.squareup.okhttp3:okhttp:3.4.1'
       compile 'com.squareup.okio:okio:1.9.0'
    }

    直接引入jar包(对Android studio 或者 Eclipse 都适用)

    1.在官网下载 sdk
    2.解压后得到 jar 包,目前包括 aliyun-oss-sdk-android-x.x.x.jarokhttp-3.x.x.jarokio-1.x.x.jar
    3.将以上 3 个 jar 包导入 libs 目录

    权限设置
    确保 AndroidManifest.xml 文件中已经配置了这些权限,否则,SDK 将无法正常工作。

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

    混淆设置

    -keep class com.alibaba.sdk.android.oss.** { *; }
    -dontwarn okio.**
    -dontwarn org.apache.commons.codec.binary.**

    实现过程

    首先为了安全起见,采用的是STS鉴权模式,则要用到的数据都是从后台获得然后应用到前台的。

    1.创建OSSClient (自己在这里命名为OssService)
    OSSClient为OSS 服务的 Android 客户端,它为调用者提供了一系列的方法,可以用来操作,管理存储空间(bucket)和文件(object)等。

    public class OssService {
       private OSS oss;
       private String bucket;
       private picResultCallback callback;//回调接口
       private String path=地址(后台告诉);
       public OssService(OSS oss, String bucket,picResultCallback callback) {
           this.oss = oss;
           this.bucket = bucket;
           this.callback=callback;
       }

     /**object字段为图片的上传地址(具体地址的前缀后端给,这个是拼起
       *来的一个路径)
       *localFile图片的本地地址
       *mProgress 进度条
       *img 显示图片的控件
       *type 类型
    */
       public void asyncPutImage(String object, final String localFile, final ProgressBar mProgress, final ImageView img,String type) {
           if (object.equals("")) {
               Log.w("AsyncPutImage", "ObjectNull");
               return;
           }
           File file = new File(localFile);
           if (!file.exists()) {
               Log.w("AsyncPutImage", "FileNotExist");
               Log.w("LocalFile", localFile);
               return;
           }
           // 构造上传请求
           PutObjectRequest put = new PutObjectRequest(bucket, object, localFile);
               put.setCallbackParam(new HashMap<String, String>() {
                   {
                       put("callbackUrl", path);
                       put("callbackBody", "filename=${object}&size=${size}&id=${x:id}&action=${x:action}");
    //https://help.aliyun.com/document_detail/31989.html?spm=5176.doc31984.6.883.brskVg
                   }
               });
           HashMap<String, String> hashMap=new HashMap<>();
           hashMap.put("x:id",id);
           hashMap.put("x:action",type);
           put.setCallbackVars(hashMap);
           // 异步上传时可以设置进度回调
           put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
               @Override
               public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                   int progress = (int) (100 * currentSize / totalSize);
                   mProgress.setProgress(progress);
               }
           });
           OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
               @Override
               public void onSuccess(PutObjectRequest request, final PutObjectResult result) {
                 Observable.just(result).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<PutObjectResult>() {
                       @Override
                       public void call(PutObjectResult putObjectResult) {
                           mProgress.setVisibility(View.GONE);
                           img.setColorFilter(null);
                           callback.getPicData(result,localFile);
                       }
                   });
               }
               @Override
               public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                   String info = "";
                   // 请求异常
                   if (clientExcepion != null) {
                       // 本地异常如网络异常等
                       clientExcepion.printStackTrace();
                       info = clientExcepion.toString();
                   }
                   if (serviceException != null) {
                       // 服务异常
                       Log.e("ErrorCode", serviceException.getErrorCode());
                       Log.e("RequestId", serviceException.getRequestId());
                       Log.e("HostId", serviceException.getHostId());
                       Log.e("RawMessage", serviceException.getRawMessage());
                       info = serviceException.toString();
                   }
               }
           });
       }
    //成功的回调接口
       public interface picResultCallback {
           void getPicData(PutObjectResult data,String oldPath);
       }
    }

    2.实现OssService的方法(在activity中)

    public OssService initOSS(String endpoint, String bucket) {
       OSSCredentialProvider credentialProvider;
       credentialProvider = new STSGetter(tokenBean);
       //设置网络参数
       ClientConfiguration conf = new ClientConfiguration();
       conf.setConnectionTimeout(15 * 1000); // 连接超时,默认15秒
       conf.setSocketTimeout(15 * 1000); // socket超时,默认15秒
       conf.setMaxConcurrentRequest(5); // 最大并发请求书,默认5个
       conf.setMaxErrorRetry(2); // 失败后最大重试次数,默认2次
       OSS oss = new OSSClient(getApplicationContext(), endpoint, credentialProvider, conf);
       return new OssService(oss, bucket, this);
    }

    3.重载 OSSFederationCredentialProvider 生成自己的获取 STS 的功能(一般自动获得 token 写在这里,在 getFederationToken() 方法中,告诉它你获得token 的规则即可)

    1>官方demo代码(自动更新token)

    public class OSSAuthCredentialsProvider extends OSSFederationCredentialProvider {

       private String mAuthServerUrl;
       private AuthDecoder mDecoder;

       public OSSAuthCredentialsProvider(String authServerUrl) {
           this.mAuthServerUrl = authServerUrl;
       }

       /**
        * set auth server url
        * @param authServerUrl
        */

       public void setAuthServerUrl(String authServerUrl) {
           this.mAuthServerUrl = authServerUrl;
       }

       /**
        * set response data decoder
        * @param decoder
        */

       public void setDecoder(AuthDecoder decoder) {
           this.mDecoder = decoder;
       }

       @Override
       public OSSFederationToken getFederationToken() throws ClientException {
           OSSFederationToken authToken;
           String authData;
           try {
               URL stsUrl = new URL(mAuthServerUrl);
               HttpURLConnection conn = (HttpURLConnection) stsUrl.openConnection();
               conn.setConnectTimeout(10000);
               InputStream input = conn.getInputStream();
               authData = IOUtils.readStreamAsString(input, OSSConstants.DEFAULT_CHARSET_NAME);
               if (mDecoder != null) {
                   authData = mDecoder.decode(authData);
               }
               JSONObject jsonObj = new JSONObject(authData);
               int statusCode = jsonObj.getInt("StatusCode");
               if (statusCode == 200) {
                   String ak = jsonObj.getString("AccessKeyId");
                   String sk = jsonObj.getString("AccessKeySecret");
                   String token = jsonObj.getString("SecurityToken");
                   String expiration = jsonObj.getString("Expiration");
                   authToken = new OSSFederationToken(ak, sk, token, expiration);
               } else {
                   String errorCode = jsonObj.getString("ErrorCode");
                   String errorMessage = jsonObj.getString("ErrorMessage");
                   throw new ClientException("ErrorCode: " + errorCode + "| ErrorMessage: " + errorMessage);
               }
               return authToken;
           } catch (Exception e) {
               throw new ClientException(e);
           }
       }

       public interface AuthDecoder {
           String decode(String data);
       }
    }

    2>自己的代码(因为自己的所有数据都是从后台获得的,而且结合rxjava没有想到可以返回数据的方式,所以采用手动更新token的方式)
    手动更新token的具体操作:

    首先token的值存在MyApp中,第一次在进入需要用到token界面时候,先获得token的值更新MyApp中的值并记录当下的时间,如果下次再次进入任何一个需要用到token的界面的时候,则判断时间是否过期,过期则重新请求token更新token的值。

    public class STSGetter extends OSSFederationCredentialProvider {
       private OSSFederationToken ossFederationToken;
       String ak;
       String sk;
       String token ;
       String expiration ;
       public STSGetter(TokenBean bean) {
           this.ak = bean.getCredentials().getAccessKeyId();
           this.sk = bean.getCredentials().getAccessKeySecret();
           this.token = bean.getCredentials().getSecurityToken();
           this.expiration = bean.getCredentials().getExpiration();
       }
       public OSSFederationToken getFederationToken() {
       return new OSSFederationToken(ak,sk,token,expiration);
       }
    }

    4.实例化 OSSClient,调用上传图片方法

    //实例化OSSClient (自己是在onCreate()中实例化的,当然考虑到token的过期问题,也有在onResume()中再次实例化一次)
    ossService = initOSS(tokenBean.getBucket().getEndPoint(), tokenBean.getBucket().getBucketName());
    //上传图片,需要根据自己的逻辑传参数
    ossService.asyncPutImage(图片在阿里上的存储路径, 本地路径, ...);

    5.回调处理图片逻辑

    /**
    * 对图片上传回来的数据进行处理
    * @param data
    */

       @Override
       public void getPicData(PutObjectResult data, String oldPath) {
           Gson gson = new Gson();
           OssUploadImage uploadImage = gson.fromJson(data.getServerCallbackReturnBody(), OssUploadImage.class);
                      ........逻辑自己写吧
    }

    ~~喵印

    640



    展开全文
  • 安卓阿里OSS上传图片三步完成+源码例子

    安卓Android阿里OSS上传图片(缩略图使用)三步完成+源码例子

    博主在做这块阿里OSS上传,也是踩过不少相关的坑,并且阿里的官方文档也是不是很详细,也翻阅不少文章,感觉有所不足,所以记录本文,希望对后面采坑的读者有所帮助,本文目前只针对安卓端OOS开发,并且后台是做好了相关的工作(使用已经搭建好的应用服务器),那么请往下看

    本文核心要点多文件的同步上传or异步上传,单文件上传博主没踩到什么坑,读者应该比博主的聪明

    1,选择图片
    2

    2,上传阿里OSS
    在这里插入图片描述

    3,发布成功
    在这里插入图片描述

    一 添加阿里OSS需要依赖(步骤一)

    添加完相关依赖,我们进入步骤二,开始

    //阿里云OSS上传文件的SDK,上传内层依赖okhttp网络框架
        compile 'com.aliyun.dpa:oss-android-sdk:+'
        compile 'com.squareup.okhttp3:okhttp:3.11.0'
        compile 'com.squareup.okio:okio:1.9.0'
    

    二 触发请求自家服务器索要授权

    在触发上传的地方
    1,发送自家网络请求,请求自家服务器索要授权
    2, 成功返回拿到需要AccessKeyId、AccessKeySecret、SecurityToken、Expiration
    3,获取这些信息后,调用阿里SDK,构建OssClient上传即可

    P层的请求

      /**
         * 上传次数
         */
        int number;
        /**
         * 成功上传(本地文件名作为key,阿里云地址为value)
         */
        List<String> success = new ArrayList<>();
        /**
         * 失败上传(返回失败文件的本地地址)
         */
        List<String> failure = new ArrayList<>();
    
        public void upOss(final List<String> uris) {
     
    
            //初始化
            number = 1;
            success.clear();
            failure.clear();
    
            mGson = new Gson();
            HashMap<String, Object> map = new HashMap<>();
            map.put("type", "release");
            String payload = mGson.toJson(map);
    
            //封装post请求参数
            Map<String, Object> listMap = new HashMap<>();
            listMap.put("code", 6022);
            listMap.put("token", SPUtil.getString(mContext, Constant.LOGIN_TOKEN, ""));
            listMap.put("payload", payload);
    
            mDraftM.getVoucherAndUpload(listMap).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new FilterSubscriber<Object>() {
    
                @Override
                public void onSubscribe(Disposable d) {
                }
    
                //服务器  给OSS 上传的 秘钥
                @Override
                public void onNext(Object data) {
                    String stringData = String.valueOf(data);
                    try {
                        JSONObject jsonObject = new JSONObject(stringData);
                        int code = jsonObject.optInt("code");
                        //需要判断code的值做不同的处理
                        if (0 == code) {
                            //请求数据成功,拆分数据
                            Upload6022Bean bean = mGson.fromJson(stringData, Upload6022Bean.class);
                            if (bean != null) {
                                //初始化阿里云OSS   秘钥
                                String accessKeyId = bean.getPayload().getAccessid();
                                String accesskeysecret = bean.getPayload().getAccesskeysecret();  //秘钥
                                String securitytoken = bean.getPayload().getSecuritytoken();
    
                                String endpoint = bean.getPayload().getHost();          //https://oss-cn-shanghai.aliyuncs.com
                                OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(accessKeyId, accesskeysecret, securitytoken);
                                OSS oss = new OSSClient(mContext, endpoint, credentialProvider);
    
                                mObjectKey = bean.getPayload().getDir();                  //hw/test/trends/
                                String bucketName = bean.getPayload().getBucketName();  //kx-common
                                mImagUrl = bean.getPayload().getImg_url();              //https://img.kx.com
    
                                for (String path : uris) {
                                    File file = new File(path);
                                    mCrypt = MD5Util.crypt(path);
                                    BitmapFactory.Options options = new BitmapFactory.Options();
                                    BitmapFactory.decodeFile(file.getAbsolutePath(), options);
    
                                    //获取图片的宽高
                                    int height = options.outHeight;
                                    int width = options.outWidth;
                                    mObjectKeyPath = mObjectKey + width + "_" + height + "_" + mCrypt + ".jpg";
    
                                    // 异步构造上传请求  核心代码 就下面几行  再走阿里,上传给阿里
                                    PutObjectRequest objectRequest = new PutObjectRequest(bucketName, mObjectKeyPath, path);
    
                                    oss.asyncPutObject(objectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
                                        @Override
                                        public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                                            String aliPath = mImagUrl + "/" + request.getObjectKey();  //https://img.kx.com/hw/test/trends/46546.jpg
                                            success.add(aliPath);
                                            if (number == uris.size()) {
                                                //返回 上传路径,以及失败的路径
                                                mJuhuaDialog.dissmiss();
                                                mPublicDyVI.onOssSuccess(success, failure);
                                            }
                                            number++;
                                        }
    
                                        @Override
                                        public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
                                            number++;
                                            String aliPath = mImagUrl + "/" + mObjectKey + mCrypt + ".jpg";
                                            failure.add(aliPath);
                                            if (number == uris.size()) {
                                                mJuhuaDialog.dissmiss();
                                                mPublicDyVI.onOssError(success, failure);
                                            }
                                        }
                                    });
    
                                    // 异步构造上传请求   end
    
    
                                    //同步
    /*                                PutObjectResult putObjectResult = oss.putObject(objectRequest);
                                    String aliPath = mImagUrl + "/" + mObjectKeyPath;//https://img.vistateach.com/hw/test/trends/bf828298f10ada9eafca4c334b971a87.jpg
                                    success.add(aliPath);
                                    if (number == uris.size()) {
                                        //返回 上传路径,以及失败的路径
                                        mJuhuaDialog.dissmiss();
                                        mPublicDyVI.onOssSuccess(success, failure);
                                    }
                                    number++;*/
                                }
                                
                            } else {
                                //TODO 获取凭证信息失败
                                mPublicDyVI.onOssError(mErrorMessage);
                            }
                        } else {
                            mPublicDyVI.onOssError(mErrorMessage);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        mPublicDyVI.onOssError(mErrorMessage);
                    }
                }
    
                @Override
                public void onComplete() {
                }
    
                @Override
                public void onError(String str) {
                    mPublicDyVI.onOssError(str);
                }
            });
    
        }
    

    三 本文核心要点多文件的同步上传or异步上传

    1,同步上传:多文件同步上传没有线程或者循环问题,就是用户体验较差,需要等待
    2,异步上传: 就有上面叙述问题,上传9张,效果返回多张图一样一样,本地拼接的麻烦

    问题:

    这里采坑是后台没做callback体封装,不返回拼接的图片下载完整地址,博主自己移动端拼接,产生循环异步问题,我们循环地址列表,循环体里面做阿里OSS上传,就会 跑1,1的回调没回来,在2的回调,回来1和2,上传OSS2张没问题,但我们本地拼接地址出问题,导致两张图一模一样.

    解决:

    通过回调的onSuccess(PutObjectRequest request, PutObjectResult result ) ,拿request里面的getObjectKey来拼接,result是没有body 因为我们可爱的后台偷懒了.

    异步请求核心代码

     // 异步构造上传请求  核心代码 就下面几行  再走阿里,上传给阿里
                                    PutObjectRequest objectRequest = new PutObjectRequest(bucketName, mObjectKeyPath, path);
    
                                    oss.asyncPutObject(objectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
                                        @Override
                                        public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                                            String aliPath = mImagUrl + "/" + request.getObjectKey();//https://img.vistateach.com/hw/test/trends/bf828298f10ada9eafca4c334b971a87.jpg
    
                                            success.add(aliPath);
                                            if (number == uris.size()) {
                                                //返回 上传路径,以及失败的路径
                                                mJuhuaDialog.dissmiss();
                                                mPublicDyVI.onOssSuccess(success, failure);
                                            }
                                            number++;
                                        }
    
                                        @Override
                                        public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
                                            number++;
                                            String aliPath = mImagUrl + "/" + mObjectKey + mCrypt + ".jpg";
                                            failure.add(aliPath);
                                            if (number == uris.size()) {
                                                mJuhuaDialog.dissmiss();
                                                mPublicDyVI.onOssError(success, failure);
                                            }
                                        }
                                    });
    
                                    // 异步构造上传请求   end
    

    同步上传 核心代码

                                    //同步
    /*                                PutObjectResult putObjectResult = oss.putObject(objectRequest);
                                    String aliPath = mImagUrl + "/" + mObjectKeyPath;//https://img.vistateach.com/hw/test/trends/bf828298f10ada9eafca4c334b971a87.jpg
                                    success.add(aliPath);
                                    if (number == uris.size()) {
                                        //返回 上传路径,以及失败的路径
                                        mJuhuaDialog.dissmiss();
                                        mPublicDyVI.onOssSuccess(success, failure);
                                    }
                                    number++;*/
                                }
    

    四 额外步骤OSS缩略图应用

    在原有访问地址拼接尾缀?x-oss-process=image/resize,m_fill,h_高度,w_宽度,提高图片加载速度,访问OSS定义缩略图,提高用户体验

    String OSS_SMALL_PIC = "?x-oss-process=image/resize,m_fill,h_200,w_200";
    

    运用核心代码

        @Override
        public void onSuccess(DyDetailBean6049.PayloadBean.NewsMapBean newsMap) {
            mTvAddDate1.setText(newsMap.getAdd_date());
            mTvActionText.setText(newsMap.getAction_text());
            mTvDyTitle.setText("课堂标题:  " + newsMap.getTitle());
            mTvDyContent.setText("课堂内容:  " + newsMap.getContent());
            mTv_lesson_time.setText("上课时间:  " + newsMap.getLesson_time());
    
            final String img_url = newsMap.getImg_url();
            if (!TextUtils.isEmpty(img_url)) {
                //图片地址数组
                final String[] split = img_url.split(",");
                //拼接缩略图尾缀
                for (int i = 0; i < split.length; i++) {
                    split[i] = split[i]+ AppConfig.OSS_SMALL_PIC;
    
                }
                ItemImgAdapter itemImgAdapter = new ItemImgAdapter(this, split);
                mRv.setLayoutManager(new GridLayoutManager(this, 3));
                mRv.setAdapter(itemImgAdapter);
    
                itemImgAdapter.setOnItemClickListener(new LessonDetaiAdapter.OnItemClickListener() {
                    @Override
                    public void onItemClick(View view, int position) {
                        // 点击查看大图
                        Intent intent = new Intent(DyDetailActivity.this, VpActivity.class);
                        intent.putExtra("paths", img_url);
                        intent.putExtra("position", position);
                        startActivity(intent);
                    }
                });
            }
        }
    

    五 尾言

    为自己技术增值,量变引起质变.对象亦来源于生活,模式亦来源于验证的OO经验,那么请学会使用轮子,再到感受制造轮子的乐趣,你会发现原来编程那么美妙.如有错误或不当之处,请读者留言,博主好吸取经验,互相交流学习,如果本文对你有帮助请帮博主点赞,发注一波,谢谢善良的读者

    展开全文
  • /** *endpoint accessKeyId 阿里云自己申请的 accessKeySecret 阿里云自己申请的 token 后台生成 */ public class OssManager extends ... private OSS oss; private UpLoadPhotoActivity mContext; publ...
  • 阿里云后台token工具类,这部分一般放在后台完成,但是如果需要移动端进度优先或者技术选型阶段可以尝试自主搭建这个后台服务 下载代码后,替换config.json中对应参数为自己家申请的参数 使用IDEA运行代码 设置对应...
  • 上个项目中使用的是阿里云OSS,查阅了官方文档,发现居然没有多文件上传相关说明文档,只有一个单文件异步上传的说明。既没有多文件上传,又没有同步上传,删除文件亦然,凌乱。想到之前做过的七牛云开发,决定用...
  • 我在使用阿里云OSS上传图片Android版的SDK,上传图片的时候发现图片上传速度很快,但是图片上传完成之后 OSS返回图片地址的时候特别慢,有没有人知道这是什么原因啊。下面是我上传图片的时候打印的Log: ![图片说明...
  • //引入阿里云oss包 implementation 'com.aliyun.dpa:oss-android-sdk:+' implementation 'com.squareup.okhttp3:okhttp:3.10.0' implementation 'com.squareup.okio:okio:1.9.0' implementati...
  • 写了个简单的阿里云Oss上传,封装成一个类,可以直接使用 首先在您的gradle中配置sdk: dependencies { compile 'com.aliyun.dpa:oss-android-sdk:+' } 然后确保您的 AndroidManifest.xml 文件中已经配置了这些...
  • 本篇博客主要介绍的是将本地图片上传到服务器的方法技巧首先附上阿里云oss官网SDK介绍:点击打开链接附上官方推荐的demo 点击打开链接在app的build中配置oss :compile 'com.aliyun.dpa:oss-android-sdk:+'技术相对...
  • Android 阿里云OSS上传

    2019-05-16 09:23:50
    1.gradle中配置sdk: dependencies { compile 'com.aliyun.dpa:oss-android-sdk:+' } 2.AndroidManifest.xml 文件中配置...uses-permission android:name="android.permission.INTERNET" /> <uses-permissio...
  • spring项目实现oss图片上传 最近写项目遇到了一些问题,因为公司刚起步,所以什么都要重新做,最近在做图片上传的时候遇到了一些问题,记录下来与大家分享. 首先我们看一下阿里云的文档 // Endpoint以杭州为例,其它...
  • 参考: 官方文档和SDK:API&amp;amp;amp;amp;amp;amp;SDK 一、在阿里云开通OOS 二、集成 三、测试
  • OSS资料可以去阿里官方...OSS集成Android Studio中 compile 'com.aliyun.dpa:oss-android-sdk:+' 1、OSS下载 根据提供url进行下载,其实也...
  • Android端使用阿里云OSS上传文件的正确姿势
  • 轻松搞定阿里OSS文件上传图片下载 一、账号准备 1. 注册阿里云账号,并开通OSS存储服务 2. 创建RAM子用户并使用子账户的AccessKeyId和AccessKeySevcret进行业务操作,主账户存在安全问题 通过管理控制...
  • import com.aliyun.oss.OSSClient; import com.aliyun.oss.model.ObjectMetadata; import com.aliyun.oss.model.PutObjectResult; import java.io.File; import java.io.IOException; import java.io.InputStream; i...
  • 最近项目有这个这块的需求,简单的记录一下使用过程,以便以后学习、使用。 直接上干货分享: ...1、前端页面有图片上传的图标,并且增加图片上传的input隐藏域,便于拿到上传的图片信息  &lt;div class...
1 2 3 4 5 ... 20
收藏数 842
精华内容 336
关键字:

oss图片上传android