文件上传工具类

作者: Fitz_e74a | 来源:发表于2019-05-24 15:51 被阅读33次

    背景

    最近由于项目需求,需要抓取上传app的日志,方便问题追踪,同时给其他公司其他项目进行依赖使用,因此需要打成aar库。

    实现

    使用Retrfit 进行网络部分的请求,Retrfit的依赖

       implementation 'com.squareup.retrofit2:retrofit:2.3.0'
        implementation "com.squareup.okhttp3:logging-interceptor:3.8.1"
    

    采用后台服务的方式,进行日志上传,同时上传完成之后,自动销毁任务,因为采用IntentService

    代码部分

    public class UploadFileService extends IntentService {
    
        private static final String TAG = "UploadFileService";
        private SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyyMMdd");
    
        private UploadServiceApi mUploadServiceApi;
    
    
        /**
         * Creates an IntentService.  Invoked by your subclass's constructor.
         *
         * @param name Used to name the worker thread, important only for debugging.
         */
        public UploadFileService(String name) {
            super(name);
        }
    
        public UploadFileService() {
            this("NEW_UPLOAD");
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            mUploadServiceApi = RetrfitApiUtil.getService(UploadServiceApi.class, "");
        }
    
        @Override
        protected void onHandleIntent(Intent intent) {
            List<File> files = getNeedUploadFiles();
            File zipFile = ZipUtils.zipFiles(files, mSimpleDateFormat.format(new Date()) + ".zip");
            Log.d(TAG, "zipFile " + zipFile.length() + zipFile.getAbsolutePath());
            RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), zipFile);
            MultipartBody.Part body = MultipartBody.Part.createFormData("file", zipFile.getName(), requestFile);
            Map<String, RequestBody> map = getUploadParamsMap();
    
            Call<ResponseBody> call = mUploadServiceApi.uploadLogFile(UploadUtil.getUrl(), map, body);
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    Log.d(TAG, "上传成功" + response.toString());
                    ZipUtils.deleteZipFile();
                }
    
                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Log.e(TAG, t.toString());
                }
            });
    
        }
    
        private Map<String, RequestBody> getUploadParamsMap() {
            Map<String, RequestBody> newMap = new HashMap<>();
            Map<String, Object> map = UploadUtil.getmParamMap();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
                newMap.put(entry.getKey(), toRequestBody(entry.getValue()));
            }
    
            return newMap;
        }
    
        private List<File> getNeedUploadFiles() {
    
            List<File> files = new ArrayList<>();
            File fileDir = new File(UploadUtil.getLocation());
            if (fileDir.isDirectory()) {
                File[] fileArray = fileDir.listFiles();
                files = new ArrayList<>(Arrays.asList(fileArray));
            }
            List<File> newFiles = new ArrayList<>();
            for (File file : files) {
                if (UploadUtil.getDatas() == null || UploadUtil.getDatas().isEmpty()) break;
                for (String fileName : UploadUtil.getDatas()) {
                    if (file.getName().contains(fileName)) {
                        newFiles.add(file);
                        break;
                    }
                }
            }
            return newFiles;
        }
    
    
        @Override
        public void onDestroy() {
            super.onDestroy();
    
        }
    
        private RequestBody toRequestBody(Object value) {
            String newValue;
            if (value instanceof String) {
                newValue = (String) value;
            } else if (value != null) {
                newValue = value.toString();
            } else {
                newValue = "";
            }
            RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), newValue);
            return requestBody;
        }
    
    }
    
    

    Retrfit接口定义

    public interface UploadServiceApi {
    
        /**
         * 上传日志文件/到服务器
         * @return
         */
        @Multipart
        @POST
        Call<ResponseBody> uploadLogFile(@Url String url, @PartMap Map<String, RequestBody> files, @Part MultipartBody.Part file);
    }
    
    

    服务器地址由接口直接传入,因此host直接传null即可

    public class RetrfitApiUtil {
    
        /**
         * @param tClass retrofitAPI 类
         * @param host   服务器地址(必须以 / 结尾)
         * @return
         */
        public static <T> T getService(Class<T> tClass, String host) {
            //网络日志
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY );
            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    .addInterceptor(interceptor);
            OkHttpClient okHttpClient = builder.connectTimeout(15000L, TimeUnit.MILLISECONDS)
                    .readTimeout(15000L, TimeUnit.MILLISECONDS)
                    .build();
    
            if (TextUtils.isEmpty(host)) {
                host = "http://localhost/";
            }
    
    
            Retrofit retrofit = new Retrofit.Builder().baseUrl(host)
                    .client(okHttpClient)
                    .build();
    
            return retrofit.create(tClass);
        }
    
    }
    
    

    可能需要进行多个文件进行上传,因此需要打包,ZipUtil工具栏

    public class ZipUtils {
    
    
        public static File zipFiles(List<File> srcFiles, String zipFileName) {
            // 判断压缩后的文件存在不,不存在则创建
            File zipFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/T3出行/Log", zipFileName);
            createOrExistsFile(zipFile);
            // 创建 FileOutputStream 对象
            FileOutputStream fileOutputStream = null;
            // 创建 ZipOutputStream
            ZipOutputStream zipOutputStream = null;
            // 创建 FileInputStream 对象
            FileInputStream fileInputStream = null;
    
            try {
                // 实例化 FileOutputStream 对象
                fileOutputStream = new FileOutputStream(zipFile);
                // 实例化 ZipOutputStream 对象
                zipOutputStream = new ZipOutputStream(fileOutputStream);
                // 创建 ZipEntry 对象
                ZipEntry zipEntry = null;
                // 遍历源文件数组
                for (int i = 0; i < srcFiles.size(); i++) {
                    // 将源文件数组中的当前文件读入 FileInputStream 流中
                    fileInputStream = new FileInputStream(srcFiles.get(i));
                    // 实例化 ZipEntry 对象,源文件数组中的当前文件
                    zipEntry = new ZipEntry(srcFiles.get(i).getName());
                    zipOutputStream.putNextEntry(zipEntry);
                    // 该变量记录每次真正读的字节个数
                    int len;
                    // 定义每次读取的字节数组
                    byte[] buffer = new byte[1024];
                    while ((len = fileInputStream.read(buffer)) > 0) {
                        zipOutputStream.write(buffer, 0, len);
                    }
                }
                if (zipEntry != null) {
                    zipOutputStream.closeEntry();
                }
                zipOutputStream.close();
                fileInputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return zipFile;
        }
    
    
        public static void deleteZipFile() {
            File zipFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/T3出行/Log");
            deleteFile(zipFile);
    
        }
        /***
         * 删除压缩后的文件
         */
        /**
         * 先根遍历序递归删除文件夹
         *
         * @param dirFile 要被删除的文件或者目录
         * @return 删除成功返回true, 否则返回false
         */
        public static boolean deleteFile(File dirFile) {
            // 如果dir对应的文件不存在,则退出
            if (!dirFile.exists()) {
                return false;
            }
    
            if (dirFile.isFile()) {
                return dirFile.delete();
            } else {
    
                for (File file : dirFile.listFiles()) {
                    deleteFile(file);
                }
            }
    
            return dirFile.delete();
        }
    
    
        /**
         * 判断文件是否存在,不存在则判断是否创建成功
         *
         * @param file 文件
         * @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败
         */
        public static boolean createOrExistsFile(final File file) {
            if (file == null) return false;
            // 如果存在,是文件则返回 true,是目录则返回 false
            if (file.exists()) return file.isFile();
            if (!createOrExistsDir(file.getParentFile())) return false;
            try {
                return file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 判断目录是否存在,不存在则判断是否创建成功
         *
         * @param file 文件
         * @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败
         */
        public static boolean createOrExistsDir(final File file) {
            // 如果存在,是目录则返回 true,是文件则返回 false,不存在则返回是否创建成功
            return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
        }
    }
    
    

    App或者其他库调用的入口UploadUtil,
    url 为上传的服务器地址,location为需要上传文件的目录,datas为需要上传文件的文件名的集合,logKey为公司项目统一要求字段,其他库可以直接传null

    public class UploadUtil {
    
        private static boolean test = false;
    
    
        /**
         * 请求参数map
         */
        private static HashMap<String, Object> mParamMap;
        private static String url;
        private static String location;
        private static List<String> datas;
        private static Context context;
    
    
        public static void setLogKey(String logKey) {
            if (mParamMap == null) {
                mParamMap = new HashMap<>();
            }
            mParamMap.put("logKey", logKey);
        }
    
        public static String getUrl() {
            return url;
        }
    
        public static void setUrl(String url) {
            UploadUtil.url = url;
        }
    
        public static String getLocation() {
            return location;
        }
    
        public static void setLocation(String location) {
            UploadUtil.location = location;
        }
    
        public static List<String> getDatas() {
            return datas;
        }
    
        public static void setDatas(List<String> datas) {
            UploadUtil.datas = datas;
        }
    
        public static HashMap<String, Object> getmParamMap() {
            return mParamMap;
        }
    
        public static void setmParamMap(HashMap<String, Object> mParamMap) {
            UploadUtil.mParamMap = mParamMap;
        }
    
    
        public static void init(Context context, HashMap<String, Object> map) {
            UploadUtil.context = context;
            mParamMap = map;
        }
    
    
        public static void prepare(String url, String location) {
            UploadUtil.url = url;
            UploadUtil.location = location;
    
        }
    
        public static void uploadFile(String logKey, List<String> datas) throws Exception {
            setLogKey(logKey);
            UploadUtil.datas = datas;
            if (test) {
                UploadUtil.datas = new ArrayList<>(Arrays.asList("Screenshot_20190506-180709.jpg", "Screenshot_20190505-102016_3D.jpg"));
            }
            if (context != null && mParamMap != null) {
                context.startService(new Intent(context, UploadFileService.class));
            } else {
                throw new Exception("please init context & paramMap first");
            }
        }
    
        public static void uploadFile(String logKey, String fileName) throws Exception {
            Log.d("UploadUtil",fileName+"===="+logKey);
            setLogKey(logKey);
            UploadUtil.datas =  new ArrayList<>(Arrays.asList(fileName));
            if (test) {
                UploadUtil.datas = new ArrayList<>(Arrays.asList("Screenshot_20190506-180709.jpg", "Screenshot_20190505-102016_3D.jpg"));
            }
            if (context != null && mParamMap != null) {
                context.startService(new Intent(context, UploadFileService.class));
            } else {
                throw new Exception("please init context & paramMap first");
            }
        }
    
    }
    
    

    使用方法

    1. 先调用UploadUtil.init()进行文件夹目录和基本上传参数的构建,比如token等
    2. 其次,调用UploadUtil.prepare()设置需要上传的服务器地址和文件目录
    3. 最后,UploadUtil.uploadFile()进行文件开始的上传,由于采用IntentService,多次调用,也会在队列里一个个进行上传,任务全部结束之后,service自动销毁

    相关文章

      网友评论

        本文标题:文件上传工具类

        本文链接:https://www.haomeiwen.com/subject/skagzqtx.html