簡體   English   中英

將Base64中的大圖像上傳到服務器

[英]Upload Large Image in Base64 to Server

我使用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使用率?

這是我的圖像/文件上傳器類:

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.";
    }
?>

如果您可以控制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());
  }

我認為問題不在於下載到服務器。 如果我理解正確,則可以從相機獲取圖像並將其發送。 注意,如果使用簡單的請求意圖,則返回onActivityResult()-位圖圖像 -這可能是OutOfMemoryException的問題...

解決方案是,它使用Intent()方法的另一種形式(可以在其參數中獲取存儲路徑)來從相機獲取照片,而不返回位圖圖像。 但是將照片保存到您指定的路徑。 現在,您可以對路徑中的照片執行任何操作,而無需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);

讓我知道,這有幫助...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM