(出处: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接收代码的更多相关文章

  1. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  2. android 线程池的使用

    转自http://www.trinea.cn/android/java-android-thread-pool/ Java(Android)线程池 介绍new Thread的弊端及Java四种线程池的 ...

  3. Android(java)学习笔记211:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  4. Android 线程池概念及使用

    一:使用线程池的原因 在android开发中经常会使用多线程异步来处理相关任务,而如果用传统的newThread来创建一个子线程进行处理,会造成一些严重的问题: 在任务众多的情况下,系统要为每一个任务 ...

  5. android线程池ThreadPoolExecutor的理解

    android线程池ThreadPoolExecutor的理解 线程池 我自己理解看来.线程池顾名思义就是一个容器的意思,容纳的就是ThreadorRunable, 注意:每一个线程都是需要CPU分配 ...

  6. 最强大的Android线程池框架

    背景 大家都知道在我们的开发中永远都离不开多线程,对于我们为什么要使用多线程,多线程的使用和多线程的一些基础知识这里我们就不讲了,有兴趣的朋友可以去看一下博主之前的几篇文章: 线程你真的了解它吗 这才 ...

  7. java 线程、线程池基本应用演示样例代码回想

    java 线程.线程池基本应用演示样例代码回想 package org.rui.thread; /** * 定义任务 * * @author lenovo * */ public class Lift ...

  8. Android线程池使用终结版

    有一段时间没写博文了,今天抽空总结一下,也希望能通过自己写的这些文章,加深理解的同时能帮 助在技术方面有疑点的朋友搞清楚个所以然来,由于经常会在网上或群里看到有朋友会问线程方面的 东西,就像我一个朋友 ...

  9. Java(Android)线程池zz

    介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new T ...

随机推荐

  1. SQLSERVER将一个文件组的数据移动到另一个文件组

    SQLSERVER将一个文件组的数据移动到另一个文件组 有经验的大侠可以直接忽视这篇文章~ 这个问题有经验的人都知道怎麽做,因为我们公司的数据量不大没有这个需求,也不知道怎麽做实验 今天求助了QQ群里 ...

  2. BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4142  Solved: 1964[Submit][Statu ...

  3. 深入研究Visual studio 2017 RC新特性

    在[Xamarin+Prism开发详解三:Visual studio 2017 RC初体验]中分享了Visual studio 2017RC的大致情况,同时也发现大家对新的Visual Studio很 ...

  4. CGI与FastCGI nginx+PHP-FPM

    本文转载自CGI与FastCGI 1.当我们在谈到cgi的时候,我们在讨论什么 最早的Web服务器简单地响应浏览器发来的HTTP请求,并将存储在服务器上的HTML文件返回给浏览器,也就是静态html. ...

  5. 手把手教你写一个RN小程序!

    时间过得真快,眨眼已经快3年了! 1.我的第一个App 还记得我14年初写的第一个iOS小程序,当时是给别人写的一个单机的相册,也是我开发的第一个完整的app,虽然功能挺少,但是耐不住心中的激动啊,现 ...

  6. 玩转ajax

    1.什么是ajax? Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的缩写. 2.ajax需要什么基础? HTML 用于建立 Web 表单并确定应 ...

  7. listview下拉刷新和上拉加载更多的多种实现方案

    listview经常结合下来刷新和上拉加载更多使用,本文总结了三种常用到的方案分别作出说明. 方案一:添加头布局和脚布局        android系统为listview提供了addfootview ...

  8. Spring异步功能

    使用 Spring 的异步功能时,实质是使用的 Servlet3 及以上版本的异步功能. Spring 的异步处理机制需要在 web.xml 中全部的 servlet 和 filter 处配置 < ...

  9. Configure a bridged network interface for KVM using RHEL 5.4 or later?

    environment Red Hat Enterprise Linux 5.4 or later Red Hat Enterprise Linux 6.0 or later KVM virtual ...

  10. 《CPU的工作过程》

    本文转载自inter官方网址:https://software.intel.com/zh-cn/articles/book-Processor-Architecture_CPU_work_proces ...