在开发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; // 这里一定要设置falsebitmap = 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;}@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {return new ViewHolder(mLayoutInflater.inflate(R.layout.image, null));}@Overridepublic void onBindViewHolder(ViewHolder holder, int position) {Glide.with(context).load(result.get(position)).centerCrop().into(holder.image);}@Overridepublic 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>() {@Overridepublic void onProgress(PutObjectRequest request, long currentSize, long totalSize) {// 在这里可以实现进度条展现功能Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);}});OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {@Overridepublic 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));}}@Overridepublic 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相关推荐

  1. Linux环境Shell脚本上传下载阿里云OSS文件

    为什么80%的码农都做不了架构师?>>>    Linux环境Shell脚本上传下载阿里云OSS文件 背景 工作中由于我们项目生成的日志文件比较重要,而本地磁盘空间有限存储不了多久, ...

  2. mysql数据库备份到oss_备份MySQL数据库并上传到阿里云OSS存储

    1. 环境配置 要将本地文件上传到阿里云oss中, 必须使用阿里云提供的工具 ossutil, 有32位,也有64位的, Linux和Windows都有.具体可以到阿里云官网下载 本文以Linux系统 ...

  3. 图片文件压缩并上传至阿里云OSS

    图片处理 Thumbnails 在进行Java开发时可以使用Thumbnails工具类对图片进行处理,旋转.裁剪.格式转换.加水印等. 使用步骤 导包 <dependency><gr ...

  4. 前端(react)上传到阿里云OSS存储 实例

    需求背景 由于现有的后台管理系统,上传的视频越来越大,加上上传视频较慢,后端小哥提出直接从前端上传视频或者其他文件到阿里云OSS存储. 阿里云OSS 阿里云OSS文档介绍,这里不做过多赘述 安装 原本 ...

  5. 微信头像下载并上传到阿里云OSS,PHP文件上传到阿里云OSS简单代码(OSS文件上传,微信头像下载,CURL下载文件,微信头像链接过期)

    (就这么个小事,有多少公司多少项目没做到!!) 微信公众号项目,后端获取到授权用户的微信头像后,要自行下载保存,不下载的话,微信返回的头像链接会在一段时间后过期,无法访问! 下面是我写的两个简单实用方 ...

  6. PHP如何下载微信语音到服务器,并将amr格式转换为MP3格式,最后上传到阿里云oss文件中

    第一步:下载微信语音到服务器中 废话不多说,直接上代码 1.总的流程方法(里面的方法在下面) 2.下载微信语音的方法 3.将微信语音的amr格式转换为MP3格式(需要使用FFmpeg,安装使用过程请看 ...

  7. java通过URL获取网络文件并上传到阿里云OSS文件服务器

    首先,先从网络上读取到文件 /*** 从网络Url中读取文件* @param urlStr 文件URL地址* @throws IOException*/public String downLoadFr ...

  8. Springboot文件上传(本地上传、阿里云oss、腾讯云、华为云、Minio上传、七牛云)

    文件上传: 本地上传.阿里云oss.腾讯云.华为云.Minio上传.七牛云. <!-- 阿里云存储 --><dependency><groupId>com.aliy ...

  9. linux centos8 将指定本地目录下的文件上传到阿里云OSS上

    使用场景:为了解决高并发问题,尤其带宽限制(阿里云最高200M,当前首页一个用户请求4M的资源,导致带宽跟不上),jenkins打包vue下的前端静态资源上传到阿里云OSS上 前提工作:因工具是jav ...

最新文章

  1. CentOS 7下启动、关闭、重启、查看MySQL服务
  2. python字符串的定义、切片、格式化、函数
  3. 对线性回归,logistic回归和一般回归的认识
  4. 一个肯德基拖着6个“拖油瓶”的百胜中国,如何赢下中国市场?
  5. Linux编程 20 shell编程(shell脚本创建,echo显示信息)
  6. ajax 示例_通过示例了解挥发
  7. php数字取反,[转+自]关于PHP7的新特性(涉及取反和disabled_functions绕过)
  8. foobar 添加歌词插件
  9. 6400万像素时代来了,小米首个入局
  10. VNPY价差交易模块
  11. sqrt numpy_NumPy sqrt()–矩阵元素的平方根
  12. Python3.x:定义一个类并且调用
  13. 探讨【IGE】的源代码【五】。
  14. Perl语言入门(05 文件)
  15. 各种数据集汇总——转载而来
  16. java毕业设计学生学习评价系统Mybatis+系统+数据库+调试部署
  17. 38、Power Query-背后的贤内助M语言
  18. 华为交换机的应用案例(小)
  19. 【PMP】关键路径法与关键链法
  20. excel工作表保护

热门文章

  1. 【SSL】2325最小转弯问题
  2. arcgis两张图层不能同时显示_arcgis如何统一不同坐标的两个图层
  3. 网络传播时延(propagation delay)与传输时延(transmission delay)
  4. 一个进入大厂的人对产品的感悟--转载
  5. PDK工艺库安装-CSMC
  6. skyline v6 三维学习软件
  7. 板书比赛计算机,清华老师们的板书惊艳朋友圈!8个板书技巧让黑板亮起来!...
  8. linux一次压缩多个文件,同时解压多个zip文件
  9. android实现三维动画制作,女娲动画制作
  10. 【转】如何在IIS7或IIS7.5中导入导出站点及应用程序池