android 图片获取裁剪上传

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">之前做的一个图片上传的小模块, 就是从本地文件或者拍照获取之后按一定比例裁剪之后上传</span>

第一次做的时候真是各种伤不起啊, 最恶心的是OOM了, 还有htc手机上面自动人脸识别覆盖自定裁剪尺寸之类一系列奇葩的问题, 以及以及base64+json上传大图片无响应问题...最近重构的时候仔细学习了一下, 之前的几个问题大概有了答案, 记录一下几个问题的解决方案, 后面放实例:


最基本的, 无论是浏览本地图片还是调用相机拍照都是通过activity的:

 <span style="white-space:pre">	</span>case R.id.actionbar_camera:
                tempUri = Uri.fromFile(tempFile);
                intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri);
                startActivityForResult(intent, REQUEST_CAMERA);
                break;
            case R.id.actionbar_gallery:
                intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");
                startActivityForResult(intent, REQUEST_GALLERY);
                break;

REQUEST_XXX是自己定义的常量, 用于在onActivityResult里面判断, 这就不多说了


这里包括之后会遇到第一个问题OOM OutOfMemory, 这个我就不细说了, 我也是看CSDN上面一篇很强大的博客才弄明白的, 总的来说就是activity之间不要传递bitmap, 放内存里基本上要爆, 这里用Uri, 统一资源标识, 你可以Uri.fromFile为图片准备一个文件地址, 这样你只要掌握这个标识就可以随意访问而不是放在内存里, 这样实在是太蠢了, 亏我之前还花了好大功夫研究怎么压缩bitmap文件...


ContentResolver resolver = getContentResolver();
        switch (requestCode) {
            case REQUEST_CAMERA:
                if (!tempFile.exists())
                    return;

                refresh();
                break;
            case REQUEST_GALLERY:
                if (data == null)
                    return;
                tempUri = data.getData();
                if (tempUri == null)
                    return;

                try {
                    InputStream is = resolver.openInputStream(tempUri);
                    FileOutputStream os = new FileOutputStream(tempFile);
                    if (is == null)
                        return;

                    int bytesRead;
                    byte[] buffer = new byte[4 * 1024];
                    while ((bytesRead = is.read(buffer)) != -1) {
                        os.write(buffer, 0, bytesRead);
                    }
                    os.flush();
                    os.close();
                    is.close();

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                refresh();
                break;



如果想浏览本地图片的同时建立一个备份, 就在onActivityResult里面把获取到的本地图片Uri变成file, 简单文件操作啦啦啦


调用裁剪也是利用activity:


 tempUri = Uri.fromFile(tempFile);

        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(tempUri, "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", aspectX);
        intent.putExtra("aspectY", aspectY);
        intent.putExtra("outputX", outputX);
        intent.putExtra("outputY", outputY);
        intent.putExtra("noFaceDetection", true);
        intent.putExtra("return-data", false);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());

        startActivityForResult(intent, REQUEST_CROP);

注意返回值"return-data" 设为false, 如果你不想把裁剪结果按照bitmap返回的话, 用uri多好, 还不会超内存


至此, 图片调用以及裁剪已经没问题了, 裁剪部分csdn有一篇很强大的博客可以找找看, 注意这里一个很恶心的属性"noFaceDetection", 有些手机在裁剪的时候因为检测到人脸, 你的裁剪框会变成正方形, 把这个值设为false就没问题了


下面再说一下图片上传, 先吐槽base64+json, 我之前没经验啦, 上传图片还是用的上传icon的方式...后来有人告诉我base64太脆了...而且我之前上传的时候, 图片稍微大一点就会导致服务器没有响应, 据说是json上传数据量有上限, 超过这个值就呵呵了, 所以最后还是乖乖模拟表单...


我把这个工具代码贡献出来了奥, 其实主体还是从网上扒的一个代码, 忘记来源了不好意思哈, 因为用asynctask比较简单, 而且因为我这边处于接口设计的考虑包装了一下返回值, 以及其他一些原因, 把这个代码改了一下, 其实改过之后就发现其实根本不难啊, 上代码:


这里用两个map分别放params还有文件, urls是服务器返回的图片链接


public class UploadUtil {
    public static final int UPLOAD_SUCCESS = 1;
    public static final int UPLOAD_FILE_NOT_EXISTS = 2;
    public static final int UPLOAD_SERVER_ERROR = 3;

    protected static final int WHAT_TO_UPLOAD = 1;
    protected static final int WHAT_UPLOAD_DONE = 2;
    private static final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
    private static final String PREFIX = "--";
    private static final String LINE_END = "\r\n";
    private static final String CONTENT_TYPE = "multipart/form-data"; // 内容类型
    private static final String TAG = "UploadUtil";
    private static final String CHARSET = "utf-8"; // 设置编码
    private static UploadUtil uploadUtil;

    private static int requestTime = 0;
    private int readTimeOut = 30 * 1000;
    private int connectTimeOut = 30 * 1000;
    private OnUploadProcessListener onUploadProcessListener;

    private UploadUtil() {

    }

    public static UploadUtil getInstance() {
        if (null == uploadUtil) {
            uploadUtil = new UploadUtil();
        }
        return uploadUtil;
    }

    public static int getRequestTime() {
        return requestTime;
    }

    public BaseResponse uploadFile(final String requestUrl, Map<String, String> paramMap, Map<String, String> files, Map<String, String> urls) {
        Map<String, File> fileMap = new HashMap<String, File>();

        for (String key : files.keySet()) {
            File tempFile = new File(files.get(key));
            if (!tempFile.exists()) {
                Log.d(TAG, "no exist 3");
                return new BaseResponse(false, "文件不存在");
            }
            fileMap.put(key, tempFile);
        }

        requestTime = 0;
        long requestTime = System.currentTimeMillis();
        long responseTime;

        try {
            URL url = new URL(requestUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setReadTimeout(readTimeOut);
            connection.setConnectTimeout(connectTimeOut);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Charset", CHARSET);
            connection.setRequestProperty("connection", "keep-alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            connection.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);

            DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
            StringBuffer sb;
            String param;

            for (String key : paramMap.keySet()) {
                sb = new StringBuffer();
                sb.append(PREFIX).append(BOUNDARY).append(LINE_END);
                sb.append("Content-Disposition: form-data; name=\"").append(key).append("\"").append(LINE_END).append(LINE_END);
                sb.append(paramMap.get(key)).append(LINE_END);
                param = sb.toString();
                Log.d(TAG, "param: " + key + " == " + param);
                dos.write(param.getBytes());
            }

            for (String key : fileMap.keySet()) {
                sb = new StringBuffer();
                sb.append(PREFIX).append(BOUNDARY).append(LINE_END);
                sb.append("Content-Disposition:form-data; name=\"").append(key).append("\"; filename=\"")
                        .append(fileMap.get(key).getName()).append("\"").append(LINE_END);
                sb.append("Content-Type:image/pjpeg" + LINE_END);
                sb.append(LINE_END);
                param = sb.toString();

                Log.d(TAG, fileMap.get(key).getName() + " == " + param);
                dos.write(param.getBytes());

                InputStream is = new FileInputStream(fileMap.get(key));
                onUploadProcessListener.initUpload((int) fileMap.get(key).length());
                byte[] bytes = new byte[4 * 1024];
                int length, curLength = 0;
                while ((length = is.read(bytes)) != -1) {
                    curLength += length;
                    dos.write(bytes, 0, length);
                    onUploadProcessListener.onUploadProcess(curLength);
                }
                is.close();
                dos.write(LINE_END.getBytes());
            }

            byte[] endData = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes();
            dos.write(endData);
            dos.flush();
            dos.close();

            responseTime = System.currentTimeMillis();
            UploadUtil.requestTime = (int) (responseTime - requestTime) / 1000;

            InputStream is = connection.getInputStream();
            sb = new StringBuffer();
            int c;
            while ((c = is.read()) != -1) {
                sb.append((char) c);
            }
            is.close();
            String entity = sb.toString();

            Log.d(TAG, "entity is " + entity);

            if (connection.getResponseCode() == 200) {
                Log.d(TAG, "request success");
                JSONObject object = new JSONObject(entity);
                int success = JSONUtil.getInt(object, "success", 0);
                String message = JSONUtil.getString(object, "message", "网络连接失败, 请检查网络设置");

                if (success != 0) {
                    Iterator<String> it = object.keys();
                    while (it.hasNext()) {
                        String key = it.next();
                        urls.put(key, JSONUtil.getString(object, key, ""));
                    }
                }

                return new BaseResponse(success != 0, message);
            } else {
                Log.d(TAG, "request error");
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return new BaseResponse(false, "网络连接失败, 请检查网络设置");
    }

    private void sendMessage(int responseCode, String responseMessage) {
        onUploadProcessListener.onUploadDone(responseCode, responseMessage);
    }

    public void setOnUploadProcessListener(OnUploadProcessListener onUploadProcessListener) {
        this.onUploadProcessListener = onUploadProcessListener;
    }

    public int getReadTimeOut() {
        return readTimeOut;
    }

    public void setReadTimeOut(int readTimeOut) {
        this.readTimeOut = readTimeOut;
    }

    public int getConnectTimeOut() {
        return connectTimeOut;
    }

    public void setConnectTimeOut(int connectTimeOut) {
        this.connectTimeOut = connectTimeOut;
    }

    public static interface OnUploadProcessListener {
        void onUploadDone(int responseCode, String message);

        void onUploadProcess(int uploadSize);

        void initUpload(int fileSize);
    }

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值