最近项目需求将图片打包成zip上传, 记录一下。
为了方便以后使用就把它写成工具类的形式吧。这里一共用到3个工具类
分别是XZip(用于压缩)、UploadUtils(文件上传类)、
ThreadPoolUtils(线程池)
一、用法
/**
*
* 应用运行前提:SD卡中放置任务文件夹(两层,第一层/mnt/sdcard/FolderZipSend/task/,
* 第二层/mnt/sdcard/FolderZipSend/task/meter1、meter2,每个子文件夹里放几幅图片)
* 执行过程中首先将task目录整体打包为sendfile.zip,然后上传至指定服务器接口
*
* @author li
*
*/
@SuppressLint({ "SdCardPath", "HandlerLeak" })
public class MainActivity extends Activity {
private Button zipsendBtn;
private ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
zipsendBtn = (Button) findViewById(R.id.button1);
zipsendBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
progressDialog = ProgressDialog.show(MainActivity.this, "压缩上传中", "请稍候");
ThreadPoolUtils.execute(runnable);
}
});
}
/**
* 压缩及上传操作
*/
Runnable runnable = new Runnable(){
@Override
public void run() {
String message = "";
message = zipAndSend();
Message msg = new Message();
msg.what = 0;
msg.obj = message;
handler1.sendMessage(msg);
}};
Handler handler1 = new Handler(){
@Override
public void handleMessage(Message msg) {
progressDialog.dismiss();
Toast.makeText(getApplicationContext(), (String)msg.obj,Toast.LENGTH_SHORT).show();
}
};
private String zipAndSend(){
File zipfile = new File(Environment.getExternalStorageDirectory()+"/Photo_ies/", "Photo_ies.zip");
if(!zipfile.exists()) {
try {
zipfile.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
return "压缩包创建出错";
}
}
try {
XZip.ZipFolder(Environment.getExternalStorageDirectory()+"/Photo_ies/",
Environment.getExternalStorageDirectory()+"/Photo_ies/"+"sendfile.zip");
} catch (Exception e) {
e.printStackTrace();
return "压缩出错";
}
// TODO 暂定链接,本例中在这个php文件内实现文件接收并指定服务端存储目录
if (null == UploadUtil.uploadFile(zipfile, "http://10.101.126.38/receive.php")) {
return "发送出错";
}
// zipfile.delete();// 删除已发送的包
return "执行成功";
}
}
二、工具类
1. XZip
/**
* Android Zip压缩解压缩
*
* @author li
* @version 1.0
*
*/
public class XZip {
public XZip() {
}
/**
* 取得压缩包中的 文件列表(文件夹,文件自选)
*
* @param zipFileString
* 压缩包名字
* @param bContainFolder
* 是否包括 文件夹
* @param bContainFile
* 是否包括 文件
* @return
* @throws Exception
*/
public static java.util.List<java.io.File> GetFileList(
String zipFileString, boolean bContainFolder, boolean bContainFile)
throws Exception {
android.util.Log.v("XZip", "GetFileList(String)");
java.util.List<java.io.File> fileList = new java.util.ArrayList<java.io.File>();
java.util.zip.ZipInputStream inZip = new java.util.zip.ZipInputStream(
new java.io.FileInputStream(zipFileString));
java.util.zip.ZipEntry zipEntry;
String szName = "";
while ((zipEntry = inZip.getNextEntry()) != null) {
szName = zipEntry.getName();
if (zipEntry.isDirectory()) {
// get the folder name of the widget
szName = szName.substring(0, szName.length() - 1);
java.io.File folder = new java.io.File(szName);
if (bContainFolder) {
fileList.add(folder);
}
} else {
java.io.File file = new java.io.File(szName);
if (bContainFile) {
fileList.add(file);
}
}
}// end of while
inZip.close();
return fileList;
}
/**
* 返回压缩包中的文件InputStream
*
* @param zipFileString
* 压缩文件的名字
* @param fileString
* 解压文件的名字
* @return InputStream
* @throws Exception
*/
public static java.io.InputStream UpZip(String zipFileString,
String fileString) throws Exception {
android.util.Log.v("XZip", "UpZip(String, String)");
java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(zipFileString);
java.util.zip.ZipEntry zipEntry = zipFile.getEntry(fileString);
return zipFile.getInputStream(zipEntry);
}
/**
* 解压一个压缩文档 到指定位置
*
* @param zipFileString
* 压缩包的名字
* @param outPathString
* 指定的路径
* @throws Exception
*/
public static void UnZipFolder(String zipFileString, String outPathString)
throws Exception {
android.util.Log.v("XZip", "UnZipFolder(String, String)");
java.util.zip.ZipInputStream inZip = new java.util.zip.ZipInputStream(
new java.io.FileInputStream(zipFileString));
java.util.zip.ZipEntry zipEntry;
String szName = "";
while ((zipEntry = inZip.getNextEntry()) != null) {
szName = zipEntry.getName();
if (zipEntry.isDirectory()) {
// get the folder name of the widget
szName = szName.substring(0, szName.length() - 1);
java.io.File folder = new java.io.File(outPathString
+ java.io.File.separator + szName);
folder.mkdirs();
} else {
java.io.File file = new java.io.File(outPathString
+ java.io.File.separator + szName);
file.createNewFile();
// get the output stream of the file
java.io.FileOutputStream out = new java.io.FileOutputStream(
file);
int len;
byte[] buffer = new byte[1024];
// read (len) bytes into buffer
while ((len = inZip.read(buffer)) != -1) {
// write (len) byte from buffer at the position 0
out.write(buffer, 0, len);
out.flush();
}
out.close();
}
}// end of while
inZip.close();
}// end of func
/**
* 压缩文件,文件夹
*
* @param srcFileString
* 要压缩的文件/文件夹名字
* @param zipFileString
* 指定压缩的目的和名字
* @throws Exception
*/
public static void ZipFolder(String srcFileString, String zipFileString)
throws Exception {
android.util.Log.v("XZip", "ZipFolder(String, String)");
// 创建Zip包
java.util.zip.ZipOutputStream outZip = new java.util.zip.ZipOutputStream(
new java.io.FileOutputStream(zipFileString));
// 打开要输出的文件
java.io.File file = new java.io.File(srcFileString);
// 压缩
ZipFiles(file.getParent() + java.io.File.separator, file.getName(),
outZip);
// 完成,关闭
outZip.finish();
outZip.close();
}// end of func
/**
* 压缩文件
*
* @param folderString
* @param fileString
* @param zipOutputSteam
* @throws Exception
*/
private static void ZipFiles(String folderString, String fileString,
java.util.zip.ZipOutputStream zipOutputSteam) throws Exception {
android.util.Log.v("XZip", "ZipFiles(String, String, ZipOutputStream)");
if (zipOutputSteam == null)
return;
java.io.File file = new java.io.File(folderString + fileString);
// 判断是不是文件
if (file.isFile()) {
java.util.zip.ZipEntry zipEntry = new java.util.zip.ZipEntry(
fileString);
java.io.FileInputStream inputStream = new java.io.FileInputStream(
file);
zipOutputSteam.putNextEntry(zipEntry);
int len;
byte[] buffer = new byte[4096];
while ((len = inputStream.read(buffer)) != -1) {
zipOutputSteam.write(buffer, 0, len);
}
zipOutputSteam.closeEntry();
} else {
// 文件夹的方式,获取文件夹下的子文件
String fileList[] = file.list();
// 如果没有子文件, 则添加进去即可
if (fileList.length <= 0) {
java.util.zip.ZipEntry zipEntry = new java.util.zip.ZipEntry(
fileString + java.io.File.separator);
zipOutputSteam.putNextEntry(zipEntry);
zipOutputSteam.closeEntry();
}
// 如果有子文件, 遍历子文件
for (int i = 0; i < fileList.length; i++) {
ZipFiles(folderString, fileString + java.io.File.separator
+ fileList[i], zipOutputSteam);
}// end of for
}// end of if
}// end of func
public void finalize() throws Throwable {
}
}
2.UploadUtils
/**
* 文件上传工具类
* @author Li
*
*/
public class UploadUtil {
private static final String TAG = "uploadFile";
private static final int TIME_OUT = 10*1000; //超时时间
private static final String CHARSET = "utf-8"; //设置编码
/**
* android上传文件到服务器
* @param file 需要上传的文件
* @param RequestURL 请求的rul
* @return 返回响应的内容
*/
public static String uploadFile(File file,String RequestURL)
{
String result = null;
String BOUNDARY = UUID.randomUUID().toString(); //边界标识 随机生成
String PREFIX = "--" , LINE_END = "\r\n";
String CONTENT_TYPE = "multipart/form-data"; //内容类型
try {
URL url = new URL(RequestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(TIME_OUT);
conn.setConnectTimeout(TIME_OUT);
conn.setDoInput(true); //允许输入流
conn.setDoOutput(true); //允许输出流
conn.setUseCaches(false); //不允许使用缓存
conn.setRequestMethod("POST"); //请求方式
conn.setRequestProperty("Charset", CHARSET); //设置编码
conn.setRequestProperty("connection", "keep-alive");
conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
if(file!=null)
{
/**
* 当文件不为空,把文件包装并且上传
*/
DataOutputStream dos = new DataOutputStream( conn.getOutputStream());
StringBuffer sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);
/**
* 这里重点注意:
* name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件
* filename是文件的名字,包含后缀名的 比如:abc.png
*/
sb.append("Content-Disposition: form-data; name=\"zipfile\"; filename=\""+file.getName()+"\""+LINE_END);
sb.append("Content-Type: application/octet-stream; charset="+CHARSET+LINE_END);
sb.append(LINE_END);
dos.write(sb.toString().getBytes());
InputStream is = new FileInputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while((len=is.read(bytes))!=-1)
{
dos.write(bytes, 0, len);
}
is.close();
dos.write(LINE_END.getBytes());
byte[] end_data = (PREFIX+BOUNDARY+PREFIX+LINE_END).getBytes();
dos.write(end_data);
dos.flush();
/**
* 获取响应码 200=成功
* 当响应成功,获取响应的流
*/
int res = conn.getResponseCode();
Log.e(TAG, "response code:"+res);
// if(res==200)
// {
Log.e(TAG, "request success");
InputStream input = conn.getInputStream();
StringBuffer sb1= new StringBuffer();
int ss ;
while((ss=input.read())!=-1)
{
sb1.append((char)ss);
}
result = sb1.toString();
Log.e(TAG, "result : "+ result);
// }
// else{
// Log.e(TAG, "request error");
// }
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
3.ThreadPoolUtils
package com.wayne.folderzipsend;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPoolUtils {
private ThreadPoolUtils(){
}
//线程池核心线程数
private static int CORE_POOL_SIZE = 5;
//线程池最大线程数
private static int MAX_POOL_SIZE = 10;
//额外线程空状态生存时间
private static int KEEP_ALIVE_TIME = 10000;
//阻塞队列。当核心线程都被占用,且阻塞队列已满的情况下,才会开启额外线程。
private static BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(
10);
//线程工厂
private static ThreadFactory threadFactory = new ThreadFactory() {
private final AtomicInteger integer = new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "myThreadPool thread:" + integer.getAndIncrement());
}
};
//线程池
private static ThreadPoolExecutor threadPool;
static {
threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,
MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, workQueue,
threadFactory);
}
/**
* 从线程池中抽取线程,执行指定的Runnable对象
* @param runnable
*/
public static void execute(Runnable runnable){
threadPool.execute(runnable);
}
}