0

Today I'm trying to upload and image to a server. I found that a lot of developers recommend the use of HttpURLConnection. The performance is very important for me, so I tried to optimize the code the most I know how to do it. The problem I faced is that the uploaded images are considerably larger than the original ones.

If anyone sees something that can be done better, it would be of great help

This is my class to upload a bitmap:

private class SubirImagen extends AsyncTask<Bitmap, Integer, APIResponse<String>> {


    String token;
    String boundary = "***" + System.currentTimeMillis() + "***";
    String crlf = "\r\n";
    String twoHyphens = "--";


    public SubirImagen(String token) {
        this.token = token;
    }

    @Override
    protected void onPostExecute(APIResponse<String> stringAPIResponse) {
        progressBar.setVisibility(View.INVISIBLE);
        if (stringAPIResponse.getErrors().isEmpty()) {
            new File(pathToFile.getPath()).delete();
            imagenCambiada = false;
            pathToFile = null;
            controler.showToast(getContext(), stringAPIResponse.getData());
        } else {
            controler.showToast(getContext(), stringAPIResponse.getErrors().get(0).getErrorMsg());
        }
        super.onPostExecute(stringAPIResponse);
    }

    @Override
    protected void onPreExecute() {
        progressBar.setVisibility(View.VISIBLE);
        progressBar.setProgress(0);
        super.onPreExecute();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        progressBar.setProgress(values[0]);
    }


    @Override
    protected APIResponse<String> doInBackground(Bitmap... bitmaps) {
        ByteArrayOutputStream bao1 = new ByteArrayOutputStream();
        bitmaps[0].compress(Bitmap.CompressFormat.JPEG, 100, bao1);
        byte[] ba1 = bao1.toByteArray();
        int size = (twoHyphens.length() * 3) + (boundary.length() * 2) + (crlf.length() * 5) +
                ("Content-Disposition: form-data; name=\"imagen\";filename=\"imagen\"".length()) +
                ba1.length;
        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL("http://192.168.137.1:8080/BochoGameAPI/usuario/uploadFotoPerfil");
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestProperty("Authorization", token);
            urlConnection.setUseCaches(false);
            urlConnection.setDoInput(true);
            urlConnection.setDoOutput(true);
            urlConnection.setRequestMethod("POST");
            urlConnection.setRequestProperty("Connection", "Keep-Alive");
            urlConnection.setRequestProperty("Cache-Control", "no-cache");
            urlConnection.setRequestProperty("ENCTYPE", "multipart/form-data");
            urlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
            urlConnection.setFixedLengthStreamingMode(size);
            DataOutputStream request = new DataOutputStream(urlConnection.getOutputStream());
            request.writeBytes(twoHyphens + boundary + crlf);
            request.writeBytes("Content-Disposition: form-data; name=\"imagen\";filename=\"imagen\"" + crlf);
            request.writeBytes(crlf);
            request.flush();
            int progress = 0;
            int bytesRead;
            byte buf[] = new byte[1024];
            BufferedInputStream bufInput = new BufferedInputStream(new ByteArrayInputStream(ba1));
            while ((bytesRead = bufInput.read(buf)) != -1) {
                // write output
                request.write(buf, 0, bytesRead);
                request.flush();
                progress += bytesRead;
                // update progress bar
                publishProgress((progress * 100) / size);
            }
            request.write(ba1);
            request.writeBytes(crlf);
            request.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
            request.flush();
            request.close();

            int code = urlConnection.getResponseCode();
            if (code != 200) {
                throw new IOException("Invalid response from server: " + code);
            }

            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    urlConnection.getInputStream()));


            String line;
            Gson gson = new Gson();
            Type typeToken = new TypeToken<APIResponse<String>>() {
            }.getType();
            APIResponse<String> apiResponse = null;
            while ((line = rd.readLine()) != null) {
                apiResponse = gson.fromJson(line, typeToken);
            }
            rd.close();
            return apiResponse;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
        return null;
    }
}

Original image, 1.57 mb:

original

Uploaded image, 4.19 mb:

enter image description here

Bocho
  • 75
  • 8
  • https://stackoverflow.com/questions/11766878/sending-files-using-post-with-httpurlconnection For similar examples to yours. ------ It might not be the sending that is the problem, but the receiver? Do you have code for the backend server and how it is handling the sent image/saving it? – JCompetence Nov 02 '21 at 13:57
  • You start with a bitmap and after cinvwrting to jpg you upload the jpg. It is unclear what you compare with the final file on your server. – blackapps Nov 02 '21 at 14:36
  • `byte[] ba1 = bao1.toByteArray();` You should log the value of `ba1.length` and compare with file size on server. – blackapps Nov 02 '21 at 14:38
  • You can replace that whole while loop with `request.write(buf, 0, bytesRead);` with one call: request.write(ba1);`. – blackapps Nov 02 '21 at 14:40
  • You are not uploading a file but a bitmap. If you wanna upload a file then upload the bytes of the file. Dont use an intermediate bitmap. Its not needed and causes your problem. – blackapps Nov 02 '21 at 14:44
  • `Using HttpURLConnection increases the size of the uploaded image` No. Wrong title. `Using an intermediate Bitmap increases the size of the uploaded file.` – blackapps Nov 02 '21 at 14:46
  • @blackapps thanks!. First, I realize that forgot to comment the line: request.write(ba1); I use the while to update the progressBar. Second, you are right. After debug ba1.length, I see that the size is bigger than the original image. I will use the file directly and see what happens – Bocho Nov 02 '21 at 14:48

0 Answers0