package cn.koolcloud.ipos.appstore.cache; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Environment; import android.os.StatFs; import android.util.Log; import cn.koolcloud.ipos.appstore.utils.Env; import cn.koolcloud.ipos.appstore.utils.Logger; import cn.koolcloud.ipos.appstore.utils.MD5; /** * download xml,json, and some static methods about operating files. * * @author Teddy * @Create 2013-10-29 */ public class FileManager { public static final String TAG_STRING = "FileManager"; public static final int DATA_SIZE_IN_MB = 25; public static final int SD_SIZE_IN_MB = 20; private static final long XML_JSON_TIME_DIFF = 3 * 24 * 60 * 60 * 1000; // the // file // will // be // deleted // after // TIME_DIFF(unit // ms). public static final long IMAGE_TIME_DIFF = 3 * 24 * 60 * 60 * 1000; // the // file // will // be // deleted // after // TIME_DIFF(unit // ms). public static final float REMOVE_FACTOR = 0.5f; public static final int MB = 1024 * 1024; public static final int BUFFER_SIZE = 1024 * 4; /** * get string from local file, or download network file and return a string * from file. * * @param * @return String a string from xml or json file. */ public static String getStringFromFileOrUrl(Context context, String path, String url, String fileNameToSave, boolean forceDownload) { String resultString = null; try { if (!forceDownload) {// false, get file from local resultString = getStringFromLocal(context, path, fileNameToSave); } if (resultString == null) { resultString = getStringFromUrlFile(context, path, url, fileNameToSave); } } catch (IOException e) { resultString = null; } return resultString; } /** * get a inputStream from local file, or download network file and return a * inputStream from file. * * @param * @return InputStream a inputStream from xml or json file. */ public static InputStream getInputStreamFromFileOrUrl(Context context, String path, String url, String fileNameToSave, boolean forceDownload) { InputStream resultInputStream = null; try { if (!forceDownload) {// false, get file from local resultInputStream = getInputStreamFromLocal(context, path, fileNameToSave); } if (resultInputStream == null) { resultInputStream = getFileFromUrl(context, path, url, fileNameToSave); } } catch (IOException e) { resultInputStream = null; } return resultInputStream; } public static InputStream getInputStreamFromFileOrUrlByPost( Context context, String path, String url, String fileNameToSave, boolean forceDownload, List<NameValuePair> parameters, boolean isNeedMD5) { InputStream resultInputStream = null; try { if (!forceDownload) {// false, get file from local resultInputStream = getInputStreamFromLocal(context, path, fileNameToSave); } if (resultInputStream == null) { InputStream is = null; BufferedInputStream bis = null; try { if (isNeedMD5) { parameters = MD5.appendAppsParameters(parameters); } BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10 * 1000); HttpConnectionParams.setSoTimeout(httpParams, 10 * 1000); HttpClient httpClinet = new DefaultHttpClient(httpParams); HttpPost request = new HttpPost(url); request.setEntity(new UrlEncodedFormEntity(parameters, HTTP.UTF_8)); Logger.d("==url==" + url); Logger.d("==parameters==" + parameters.toString()); HttpResponse response = httpClinet.execute(request); Logger.d("==StatusCode==" + response.getStatusLine().getStatusCode()); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { HttpEntity entity = response.getEntity(); // Logger.debug(TAG_STRING, "==result=="+ // EntityUtils.toString(entity)); is = entity.getContent(); if(fileNameToSave == null) { return is; } else { bis = new BufferedInputStream(is, 8192); return getInputStream(context, path, fileNameToSave, bis); } } } catch (Exception e) { Logger.d("Error in File Download:" + e.getMessage()); e.printStackTrace(); return null; } } } catch (IOException e) { resultInputStream = null; } return resultInputStream; } public static InputStream getInputStreamFromFileOrUrlByPost( Context context, String path, String url, String fileNameToSave, boolean forceDownload, List<NameValuePair> parameters, boolean isNeedMD5, boolean formatIsJson) { InputStream resultInputStream = null; try { if (!forceDownload) {// false, get file from local resultInputStream = getInputStreamFromLocal(context, path, fileNameToSave); } if (resultInputStream == null) { InputStream is = null; BufferedInputStream bis = null; try { if (isNeedMD5) { if(formatIsJson) { parameters = MD5.appendAppsParametersJSON(parameters); } else { parameters = MD5.appendAppsParameters(parameters); } } BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10 * 1000); HttpConnectionParams.setSoTimeout(httpParams, 10 * 1000); HttpClient httpClinet = new DefaultHttpClient(httpParams); HttpPost request = new HttpPost(url); request.setEntity(new UrlEncodedFormEntity(parameters, HTTP.UTF_8)); Logger.d("==url==" + url); Logger.d("==parameters==" + parameters.toString()); HttpResponse response = httpClinet.execute(request); Logger.d("==StatusCode==" + response.getStatusLine().getStatusCode()); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { HttpEntity entity = response.getEntity(); // Logger.debug(TAG_STRING, "==result=="+ // EntityUtils.toString(entity)); is = entity.getContent(); if(fileNameToSave == null) { return is; } else { bis = new BufferedInputStream(is, 8192); return getInputStream(context, path, fileNameToSave, bis); } } } catch (Exception e) { Logger.d("Error in File Download:" + e.getMessage()); e.printStackTrace(); return null; } } } catch (IOException e) { resultInputStream = null; } return resultInputStream; } public static final String multipart_form_data = "multipart/form-data"; public static final String twoHyphens = "--"; public static final String boundary = "----WebKitFormBoundarySnxMMaE8drOymB2v"; // data separator public static final String lineEnd = System.getProperty("line.separator"); // The value is "\r\n" in Windows. /** * @param context * @param path * @param url * @param fileNameToSave * @param forceDownload * @param parameters * @param formatIsJson * @return */ public static String getInputStreamByPostMultipart2(String actionUrl, Set<Map.Entry<Object,Object>> params) { HttpURLConnection conn = null; DataOutputStream output = null; BufferedReader input = null; try { URL url = new URL(actionUrl); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(30000); conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "keep-alive"); conn.setRequestProperty("Content-Type", multipart_form_data + "; boundary=" + boundary); conn.addRequestProperty("Accept", "application/json, text/javascript, */*; q=0.01"); conn.connect(); output = new DataOutputStream(conn.getOutputStream()); addFormField(params, output); output.writeBytes(twoHyphens + boundary + twoHyphens +lineEnd); output.flush(); int code = conn.getResponseCode(); if(code != 200) { Logger.d("Error in File Download, getResponseCode=" + code); return null; } input = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder response = new StringBuilder(); String oneLine; while((oneLine = input.readLine()) != null) { response.append(oneLine + lineEnd); } return response.toString(); } catch (IOException e) { Logger.w("Error in post Multipart=" + e); return null; } finally { try { if(output != null) { output.close(); } if(input != null) { input.close(); } } catch (IOException e) { Logger.w("Error in finally=" + e); } if(conn != null) { conn.disconnect(); } } } /** * @param context * @param path * @param url * @param fileNameToSave * @param forceDownload * @param parameters * @param formatIsJson * @return */ /* public static String getInputStreamByPostMultipart(String actionUrl, Set<Map.Entry<Object,Object>> params) { Logger.debug(TAG_STRING, "post Multipart,actionUrl=" + actionUrl + ", params="+params.toString()); try { BasicHttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 10 * 1000); HttpConnectionParams.setSoTimeout(httpParams, 20 * 1000); HttpClient httpClinet = new DefaultHttpClient(httpParams); HttpPost request = new HttpPost(actionUrl); */ // request.setHeader("Accept", "application/json, text/javascript, */*; q=0.01"); /* MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT); for (Map.Entry<Object,Object> entry : params) { FormBodyPart formBodyPart = new FormBodyPart((String)entry.getKey(), new StringBody((String)entry.getValue())); multipartEntity.addPart(formBodyPart); } request.setEntity(multipartEntity); HttpResponse response = httpClinet.execute(request); int status = response.getStatusLine().getStatusCode(); Logger.debug(TAG_STRING, "post Multipart,status=" + status); if(status == 200) { HttpEntity r_entity = response.getEntity(); String responseString = EntityUtils.toString(r_entity); Logger.debug(TAG_STRING, "post Multipart,responseString=" +responseString); return responseString; } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } */ private static void addFormField(Set<Map.Entry<Object,Object>> params, DataOutputStream output) { StringBuilder sb = new StringBuilder(); for(Map.Entry<Object, Object> param : params) { sb.append(twoHyphens + boundary + lineEnd); sb.append("Content-Disposition: form-data; name=\"" + param.getKey() + "\"" + lineEnd); sb.append(lineEnd); sb.append(param.getValue() + lineEnd); } try { output.writeBytes(sb.toString()); } catch (IOException e) { Logger.w("addFormField Error=" + e); } } private static InputStream getInputStreamFromLocal(Context context, String path, String fileNameToSave) throws IOException { File file = new File(Env.getDataDirectoryPath(path), fileNameToSave); if (!file.exists()) { return null; } updateFileTime(file); return new FileInputStream(file); } private static String getStringFromLocal(Context context, String path, String fileNameToSave) throws IOException { File file = new File(Env.getDataDirectoryPath(path), fileNameToSave); if (!file.exists()) { return null; } updateFileTime(file); FileInputStream fis = new FileInputStream(file); return convertStreamToString(fis); } public static InputStream getFileFromUrl(Context context, String path, String url, String fileNameToSave) { Logger.d("download url = " + url); InputStream bis = download(url); if (bis == null) { return null; } return getInputStream(context, path, fileNameToSave, bis); } private static InputStream getInputStream(Context context, String path, String fileNameToSave, InputStream bis) { if (bis == null) { return null; } if (fileNameToSave == null) {// don't save file return bis; } if (canWriteData()) { reduceCache(Env.getAppDataDirectory(), DATA_SIZE_IN_MB, freeSpaceOnData(Environment.getDataDirectory().getPath()), XML_JSON_TIME_DIFF); } else { return bis; } File file = new File(Env.getDataDirectoryPath(path), fileNameToSave); FileOutputStream fos = null; try { fos = new FileOutputStream(file); } catch (FileNotFoundException e1) { return bis; } BufferedOutputStream bos = new BufferedOutputStream(fos); try { writeFile(bis, bos); } catch (IOException e1) { file.delete(); } finally { try { bis.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } try { return new FileInputStream(file); } catch (FileNotFoundException e) { return null; } } private static String getStringFromUrlFile(Context context, String path, String url, String fileNameToSave) { InputStream bis = getFileFromUrl(context, path, url, fileNameToSave); if (bis == null) { return null; } return convertStreamToString(bis); } public static InputStream download(String url) { InputStream is = null; try { URLConnection conn = new URL(url).openConnection(); conn.connect(); conn.setConnectTimeout(10000); is = conn.getInputStream(); } catch (Exception e) { e.printStackTrace(); is = null; } return is; } public static boolean canWriteData() { long folderSizeInMb = getFileSize(Env.getAppDataDirectory()) / MB; return folderSizeInMb < DATA_SIZE_IN_MB; } public static boolean canWriteSD() { long folderSizeInMb = 0; if (exsitSdcard()) { folderSizeInMb = getFileSize(Env.getExternalStorageDirectory()) / MB; return folderSizeInMb < SD_SIZE_IN_MB; } else { return false; } } private static void writeFile(InputStream bis, OutputStream bos) throws IOException { int r = 0; byte[] buffer = new byte[2048]; while ((r = bis.read(buffer)) != -1) { bos.write(buffer, 0, r); } bos.flush(); } public static String convertStreamToString(InputStream is) { if (is == null) { return null; } try { StringBuffer out = new StringBuffer(); byte[] b = new byte[4096]; for (int n; (n = is.read(b)) != -1;) { out.append(new String(b, 0, n)); } return out.toString(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } /** * count the size of the directory, when the size is larger than CACHE_SIZE * , or the rest room of sdcard is smaller the FREE_SD_SPACE_TO_CACHE, * delete the 40% files which were not lately used. * * @param dirPath * @param filename */ public static void reduceCache(File dir, int maxMB, int freeSpaceOnDataOrSd, long time_diff) { File[] files = dir.listFiles(); if (files == null) { return; } int dirSize = 0; for (int i = 0; i < files.length; i++) { if (!removeExpiredCache(files[i], time_diff)) dirSize += files[i].length(); } if (dirSize > maxMB * MB || maxMB > freeSpaceOnDataOrSd) { int removeFactor = (int) ((REMOVE_FACTOR * files.length)); Arrays.sort(files, new FileLastModifComparator()); for (int i = 0; i < removeFactor; i++) { files[i].delete(); } } } /** * get folder size * * @param file * @return */ public static long getFileSize(File file) { long size = 0; File fList[] = file.listFiles(); for (int i = 0; i < fList.length; i++) { if (fList[i].isDirectory()) { size = size + getFileSize(fList[i]); } else { size = size + fList[i].length(); } } return size; } /** * judge the sdcard is available or not * * @return */ public static boolean exsitSdcard() { boolean ret = false; String sDcString = Environment.getExternalStorageState(); if (sDcString.equals(Environment.MEDIA_MOUNTED)) { ret = true; } return ret; } public static int freeSpaceOnData(String path) { StatFs stat = new StatFs(path); double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat .getBlockSize()) / MB; return (int) sdFreeMB; } /** * remove expired files * * @param dirPath * @param filename */ public static boolean removeExpiredCache(File file, long time_diff) { if (System.currentTimeMillis() - file.lastModified() > time_diff) { return file.delete(); } return false; } /** * clear file cache on disk. */ public static void deleteAll(File dir) { File[] files = dir.listFiles(); if (files == null) return; for (File f : files) { if (f.isDirectory()) { deleteAll(f); f.delete(); } else { f.delete(); } } } /** * update the LastModified time of the file * * @param dir * @param fileName */ public static void updateFileTime(File file) { long newModifiedTime = System.currentTimeMillis(); file.setLastModified(newModifiedTime); } /** * file comparator */ public static class FileLastModifComparator implements Comparator<File> { @Override public int compare(File arg0, File arg1) { if (arg0.lastModified() > arg1.lastModified()) { return 1; } else if (arg0.lastModified() == arg1.lastModified()) { return 0; } else { return -1; } } } public static InputStream getStringStream(String sInputString) { ByteArrayInputStream tInputStringStream = null; if (sInputString != null && !sInputString.trim().equals("")) { tInputStringStream = new ByteArrayInputStream( sInputString.getBytes()); } return tInputStringStream; } public static File createSDDir(String dirName) { String sdpath = Environment.getExternalStorageDirectory() + "/"; File dir = new File(sdpath + dirName); dir.mkdir(); return dir; } public static File createSDFile(String fileName) throws IOException { String sdpath = Environment.getExternalStorageDirectory() + "/"; File file = new File(sdpath + fileName); file.createNewFile(); return file; } public static File write2SDFromInput(String path, String fileName, InputStream input) { File file = null; OutputStream output = null; try { createSDDir(path); file = createSDFile(path + fileName); output = new FileOutputStream(file); byte[] buffer = new byte[BUFFER_SIZE]; while ((input.read(buffer)) != -1) { output.write(buffer); } output.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { output.close(); } catch (IOException e) { e.printStackTrace(); } } return file; } /** * @Title: isFileExists * @Description: check if the file exist * @param @param context * @param @param fileName * @param @param fileSize * @param @return * @return boolean * @throws */ public static boolean isFileExists(Context context, String fileName, long fileSize) { File file = new File(fileName); if (file.exists()) { if (file.length() == fileSize) { return true; } } return false; } /** * install apk */ public static void installApk(Context ctx, File file) { // File apkfile = new File(file); if (!file.exists()) { return; } Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse("file://" + file.toString()), "application/vnd.android.package-archive"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ctx.startActivity(intent); } }