将Base64中的大图像上传到服务器

时间:2016-06-01 06:44:59

标签: java android image

我使用android.hardware.Camera API拍照。然后我将其转换为实际大小的一半的位图,将其压缩为质量为80的JPEG,将其转换为Base64并将其发送到服务器,如下所示。

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
String encoded = Base64.encodeToString(byteArray, Base64.NO_WRAP);
String json_response = "";

try {
    URL url = new URL("https://example.com/api_endpoint");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setReadTimeout(15000);
    conn.setConnectTimeout(15000);
    conn.setRequestMethod("POST");
    conn.setDoInput(true);
    conn.setDoOutput(true);
    OutputStream os = conn.getOutputStream();
    BufferedWriter writer = new BufferedWriter(
            new OutputStreamWriter(os, "UTF-8"));
    writer.write("?reg=" + regCode);
    writer.write("&img=" + encoded);
    writer.flush();
    writer.close();
    os.close();
    Log.d("Auth", conn.getResponseCode() + "");
    InputStreamReader in = new InputStreamReader(conn.getInputStream());
    BufferedReader br = new BufferedReader(in);
    String text = "";
    while ((text = br.readLine()) != null) {
        json_response += text;
    }
    conn.disconnect();
} catch (IOException e) {
    Log.d(getClass().getName(), "" + e.getMessage());
}  

这可以按预期工作。现在,如果我没有调整图像大小并保持100%的质量,我应该如何避免OutOfMemoryError?我的应用程序要求图像具有全分辨率和最佳质量。

我的问题是:

  1. 我上传正确方式的方式是什么?
  2. 如何发送图像是没有OutOfMemoryError的最佳质量,即如何在此过程中优化RAM使用?

3 个答案:

答案 0 :(得分:2)

这是我的图片/文件上传器类:

public class ImageUploader extends AsyncTask<String, String, String> {

    File imageFile = null;
    String fileName = null;

    public ImageUploader(File imageFile, String fileName){
        this.imageFile = imageFile;
        this.fileName = fileName;
    }

    @Override
    protected String doInBackground(String... params) {
        String url_str = params[0];

        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
        String Tag="fSnd";

        try {
            URL url = new URL(url_str);
            HttpURLConnection c = (HttpURLConnection) url.openConnection();

            c.setRequestMethod("POST");

            c.setDoInput(true);
            c.setDoOutput(true);

            c.setRequestProperty("Connection", "Keep-Alive");
            c.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

            c.connect();

            DataOutputStream dos = new DataOutputStream(c.getOutputStream());

            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + this.fileName + "\"" + lineEnd);
            dos.writeBytes(lineEnd);

            FileInputStream fin = new FileInputStream(imageFile);

            int bytesAvailable = fin.available();

            int maxBufferSize = 1024;
            int bufferSize = Math.min(bytesAvailable, maxBufferSize);
            byte[ ] buffer = new byte[bufferSize];

            int bytesRead = fin.read(buffer, 0, bufferSize);

            while (bytesRead > 0)
            {
                dos.write(buffer, 0, bufferSize);
                bytesAvailable = fin.available();
                bufferSize = Math.min(bytesAvailable,maxBufferSize);
                bytesRead = fin.read(buffer, 0,bufferSize);
            }


            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

            fin.close();
            dos.flush();
            dos.close();

            StringBuilder response = new StringBuilder();
            BufferedReader reader = new BufferedReader(new InputStreamReader(c.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }

            return response.toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {

        }

        return null;
    }
}

用法:

new ImageUploader(pictureFile, "sample.jpg"){
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
    }
}.execute("http://example/upload.php");

PHP:

<?php
    $file = explode('.', $_FILES['file']['name']);
    $ext = $file[count($file) - 1];
    $name = substr($_FILES['file']['name'], 0, (strlen($ext) + 1) * -1);
    $location = 'images/';
    $cntr = 1;
    $tmp_name = $name;
    if(move_uploaded_file($_FILES['file']['tmp_name'], $location.$tmp_name.'.'.$ext)){
        echo "Image was uploaded.";
    }else{
        echo "Image was not uploaded.";
    }
?>

答案 1 :(得分:1)

如果您可以控制API端点。然后尝试实现POST请求以接受来自客户端的多部分上载。

在客户端,有这样的东西将图像上传到API(使用Okhttp客户端)

  private static final String IMGUR_CLIENT_ID = "...";
  private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

  private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
    RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("title", "Square Logo")
        .addFormDataPart("image", "logo-square.png",
            RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
        .build();

    Request request = new Request.Builder()
        .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
        .url("https://api.imgur.com/3/image")
        .post(requestBody)
        .build();

    Response response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    System.out.println(response.body().string());
  }

答案 2 :(得分:0)

我认为问题不是下载到服务器。如果我理解正确,你从相机获取图像并发送它。请注意,如果使用简单请求意图,则返回onActivityResult() - 位图图像 - 这可能是OutOfMemoryException ...

解决方案它在Intent()方法上使用另一种形式(可以在他的参数中获取存储路径)从相机获取照片,但不会返回Bitmap图像。但是将照片保存到您指定的路径。现在你可以在路径中对照片做任何事情,没有OutOfMemoryException ...

示例开始正确意图:

File destination = new   File(Environment.getExternalStorageDirectory(),
                             "image.jpg");

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                 intent.putExtra(MediaStore.EXTRA_OUTPUT,
                 Uri.fromFile(destination));
startActivityForResult(intent, CAMERA_PICTURE);

让我知道,这有助于......