-Android -线程池 批量上传图片 -附php接收代码
(出处:http://www.cnblogs.com/linguanh/)
目录:
1,前序
2,类特点
3,用法
4,java代码
5,php代码
1,前序
还是源于重构,看着之前为赶时间写着的碎片化的代码,甚是悲剧,臃肿且长,其实重构也是一个提高的过程,重构过程中会接触到更多的知识点。至少,我现在意识到,那怕是听过、有这样的意识而没真正动过手都是不行的,多线程并发最好使用线程池而不要一味地 new Thread(...).start()。下面我分享个自己刚写好的图片批量上传类,顺带server端接口代码,已经过测试,一套直接可用。
2,本类特点
1、耦合度低,操作简单、使用时仅 6 行代码即可直接 批量上传完图片;
2、使用的是软化线程池对象,内存消耗这方面可以放心地交给系统处理;
3、采用链式操作,配置方便;
4、自带上传函数,光学习这个都够了;
5、懒人必备...
3,使用例子
new PicUpLoadExecutor(3)// 并发数
.withUpLoadUrl(url) // 服务端接口文件的url
.withHandler(handler) // 发完后发消息的handler
.exec(picBitmaps); // 要上传的图片bitmaps
4,client端java类
注释已经很丰富,不懂请留言
package cn.share.bananacloud.post.send; import android.graphics.Bitmap;
import android.os.Handler;
import android.util.Log; import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; /**
* Created by 林冠宏 on 2016/4/30.
*
* 1,线程池批量上传图片类,选用 newFixedThreadPool
* 2,以 Bitmap 数组为例子
* 3,自定义一个 图片上传 函数
*
*/ public class PicUpLoadExecutor { private static final String TAG = "PicUpLoadHelper";
public static final int UpLoadFinish = 0x321; /** 如果你不想内存不足是它们被gc掉,请换为强引用 */
private SoftReference<ExecutorService> fixedThreadPool = null; /** 并发数>0 --1 ~ 128,用 short 足以 */
private short poolSize = 1;
private Handler handler = null;
private ExecListenter ExecListenter;
private String url = null; public PicUpLoadExecutor(short poolSize){
fixedThreadPool = new SoftReference<ExecutorService>(Executors.newFixedThreadPool(poolSize));
} public PicUpLoadExecutor(short poolSize,ThreadFactory threadFactory){
fixedThreadPool = new SoftReference<ExecutorService>(Executors.newFixedThreadPool(poolSize,threadFactory));
} /** 设置并发数 */
/*public PicUpLoadExecutor withPoolSize(short poolSize){
this.poolSize = poolSize;
return this;
}*/ /** 设置图片总数,已直接换为图片数目 */
/*public PicUpLoadHelper withPicSize(short poolSize){
this.picSize = picSize;
return this;
}*/ /** 设置图片上传路径 */
public PicUpLoadExecutor withUpLoadUrl(String url){
this.url = url;
return this;
} /** 设置handler */
public PicUpLoadExecutor withHandler(Handler handler){
this.handler = handler;
return this;
} /** 设置自定义 run 函数接口 */
/*public PicUpLoadHelper withExecRunnableListenter(ExecRunnableListenter ExecRunnableListenter){
this.ExecRunnableListenter = ExecRunnableListenter;
return this;
}*/ /** 设置开始前接口 */
public PicUpLoadExecutor withBeforeExecListenter(ExecListenter ExecListenter){
this.ExecListenter = ExecListenter;
return this;
} public ExecutorService getFixedThreadPool(){
return fixedThreadPool.get();
} /** 开发原则--接口分离 */ /** 自定义run接口 */
public interface ExecRunnableListenter{
void onRun(int i);
} /** 开始任务前接口,没用到,可自行设置 */
public interface ExecListenter{
void onBeforeExec();
} /** 为减少 程序计数器 每次在循环时花费在 if else 的时间,这里还是 重载一次 好 */ public void exec(final Bitmap[] bitmaps,final ExecRunnableListenter ExecRunnableListenter){
if(bitmaps==null){
return;
}
if(ExecRunnableListenter!=null){
int picNums = bitmaps.length;
for(int i=0;i<picNums;i++){
/** 自定义执行上传任务 */
final int picIndex = i;
fixedThreadPool.get().execute(new Runnable() {
@Override
public void run() {
ExecRunnableListenter.onRun(picIndex);
}
});
}
}
} public void exec(final Bitmap[] bitmaps){
if(bitmaps==null){
return;
}
int picNums = bitmaps.length;
for(int i=0;i<picNums;i++){
/** 默认执行上传任务 */
final int picIndex = i;
fixedThreadPool.get().execute(new Runnable() {
@Override
public void run() {
/** 批量 上传 图片,此静态函数若有使用全局变量,必须要 加 synchronized */
String json = uploadPic
(
url,
"" + picIndex + ".jpg", /** 我自己情况的上传 */
bitmaps[picIndex] /** 对应的图片流 */
);
if(json!=null){
/** 服务器上传成功返回的标示, 自己修改吧,我这里是我的情况 */
if(json.trim().equals("yes")){
/** UpLoadFinish 是每次传完一张发信息的信息标示 */
handler.sendEmptyMessage(UpLoadFinish);
}
}
Log.d(TAG,"pic "+picIndex+" upLoad json ---> "+json);
}
});
}
} /** 若有依赖全局变量必须加 synchronized */
/** 此函数采用 tcp 数据包传输 */
public static String uploadPic(String uploadUrl,String filename,Bitmap bit){
String end = "\r\n"; /** 结束符 */
String twoHyphens = "--";
String boundary = "******"; /** 数据包头,设置格式没强性要求 */
int compress=100; /** 压缩初始值 */
try{
HttpURLConnection httpURLConnection
= (HttpURLConnection) new URL(uploadUrl).openConnection();
/** 设置每次传输的流大小,可以有效防止手机因为内存不足崩溃 */
/** 此方法用于在预先不知道内容长度时启用没有进行内部缓冲的 HTTP 请求正文的流。*/
httpURLConnection.setChunkedStreamingMode(256 * 1024);// 256K httpURLConnection.setConnectTimeout(10*1000);
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
httpURLConnection.setUseCaches(false); httpURLConnection.setRequestMethod("POST");
/** tcp链接,防止丢包,需要进行长链接设置 */
httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
httpURLConnection.setRequestProperty("Charset", "UTF-8");
httpURLConnection.setRequestProperty("Content-Type","multipart/form-data;boundary=" + boundary); /** 发送报头操作,dos 也是流发送体 */
DataOutputStream dos = new DataOutputStream(httpURLConnection.getOutputStream());
dos.writeBytes(twoHyphens + boundary + end);
/** uploadedfile 是接口文件的接受流的键,client 和 server 要同步 */
dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\"; filename=\""
+ filename.substring(filename.lastIndexOf("/") + 1)
+ "\""
+ end);
dos.writeBytes(end); /** 下面是压缩操作 */
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
while (baos.toByteArray().length / 1024 > 500) {
Log.d(TAG,"compress time ");
baos.reset();
compress -= 10;
if(compress==0){
bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
break;
}
bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
} /** 发送比特流 */
InputStream fis = new ByteArrayInputStream(baos.toByteArray());
byte[] buffer = new byte[10*1024]; // 8k+2k
int count = 0;
while ((count = fis.read(buffer)) != -1) {
dos.write(buffer, 0, count);
}
fis.close();
dos.writeBytes(end);
dos.writeBytes(twoHyphens + boundary + twoHyphens + end);
dos.flush(); /** 获取返回值 */
InputStream is = httpURLConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
String result = br.readLine(); Log.d(TAG, "send pic result "+result);
dos.close();
is.close();
return result;
} catch (Exception e){
e.printStackTrace();
Log.d(TAG, e.toString());
return null;
}
}
}
5,server端接受代码 php
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2016/4/30
* Time: 15:37
*/ // $_FILES['uploadedfile']['name'] 是传过来的图片名称 $target_path = "要保存到的路径"; if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "yes";
} else{
echo "no";
} ?>
-Android -线程池 批量上传图片 -附php接收代码的更多相关文章
- Android(java)学习笔记267:Android线程池形态
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
- android 线程池的使用
转自http://www.trinea.cn/android/java-android-thread-pool/ Java(Android)线程池 介绍new Thread的弊端及Java四种线程池的 ...
- Android(java)学习笔记211:Android线程池形态
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
- Android 线程池概念及使用
一:使用线程池的原因 在android开发中经常会使用多线程异步来处理相关任务,而如果用传统的newThread来创建一个子线程进行处理,会造成一些严重的问题: 在任务众多的情况下,系统要为每一个任务 ...
- android线程池ThreadPoolExecutor的理解
android线程池ThreadPoolExecutor的理解 线程池 我自己理解看来.线程池顾名思义就是一个容器的意思,容纳的就是ThreadorRunable, 注意:每一个线程都是需要CPU分配 ...
- 最强大的Android线程池框架
背景 大家都知道在我们的开发中永远都离不开多线程,对于我们为什么要使用多线程,多线程的使用和多线程的一些基础知识这里我们就不讲了,有兴趣的朋友可以去看一下博主之前的几篇文章: 线程你真的了解它吗 这才 ...
- java 线程、线程池基本应用演示样例代码回想
java 线程.线程池基本应用演示样例代码回想 package org.rui.thread; /** * 定义任务 * * @author lenovo * */ public class Lift ...
- Android线程池使用终结版
有一段时间没写博文了,今天抽空总结一下,也希望能通过自己写的这些文章,加深理解的同时能帮 助在技术方面有疑点的朋友搞清楚个所以然来,由于经常会在网上或群里看到有朋友会问线程方面的 东西,就像我一个朋友 ...
- Java(Android)线程池zz
介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new T ...
随机推荐
- 微信公众号开发之VS远程调试
目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 前言 微信公众平台消息接口的工作原理大概可以这样理解:从用户端到公众号端一个流 ...
- Coroutine in Java - Quasar Fiber实现--转载
转自 https://segmentfault.com/a/1190000006079389?from=groupmessage&isappinstalled=0 简介 说到协程(Corout ...
- 就这么漂来漂去---一个毕业三个月的java程序员的裸辞风波
注:这并不是一篇技术文章,而是记录了我这几个月经历的入职,裸辞,找工作的心路历程,简单介绍一个博主的情况,我是16年毕业生,校招进了一家北京的公司,java开发,和很多年轻人一样,干了一段时间,我发现 ...
- 我这么玩Web Api(一):帮助页面或用户手册(Microsoft and Swashbuckle Help Page)
前言 你需要为客户编写Api调用手册?你需要测试你的Api接口?你需要和前端进行接口对接?那么这篇文章应该可以帮到你.本文将介绍创建Web Api 帮助文档页面的两种方式,Microsoft Help ...
- 使用rowid抽取数据方法以及大数据量游标卡住的应对
平时工作的时候,经常会遇到这种事情,从一个大表A中,抽取字段a在一个相对较小B的表的数据,比如,从一个详单表中,抽取几万个用户号码的话单出来.这种时候,一般来说, 做关联查询: create tabl ...
- 【搬砖】安卓入门(1)- Java开发入门
01.01_计算机基础知识(计算机概述)(了解) A:什么是计算机?计算机在生活中的应用举例 计算机(Computer)全称:电子计算机,俗称电脑.是一种能够按照程序运行,自动.高速处理海量数据的现代 ...
- (转) 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)
原文地址: http://www.cnblogs.com/lyhabc/p/4682986.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第三篇,这一篇才真正开始搭建Alwa ...
- win10系统下连接无线网络掉线问题解决办法
打开驱动精灵----系统诊断 找一个可修复的驱动点击 选择连不上网中的查看更多 有连不上网络,网络连接受限,解决无线间歇性掉网问题 进入计算机管理----设备管理 修改无线网络属性(名称含有wirel ...
- JavaScript 写计算器改进版
<html><head><style> .short{height:50px;width:55px;float:left;}</style></h ...
- 《AngularJS深度剖析与最佳实践》简介
由于年末将至,前阵子一直忙于工作的事务,不得已暂停了微信订阅号的更新,我将会在后续的时间里尽快的继续为大家推送更多的博文.毕竟一个人的力量微薄,精力有限,希望大家能理解,仍然能一如既往的关注和支持sh ...