Search code examples
javaandroidimagebase64imgur

Android: Encode Image (of type File) to Base64


In Java, how would I encode an Image (of type File) into base64. I'm trying to upload this image from an Android app to Imgur. Thanks!


Solution

  • Well, if you are using the Apache HTTP client for connecting to the service. I would recommend using MultiPartEntity for submitting the image. I am not sure as to exactly why, but when I tried Base64, I ran into issues when the image was huge (OOM exceptions).

    To submit the image using the Apache HTTP client. All you need to do is create a MultiPartEntity and add the image using addPart.

    public class UploadImagePayload extends MultiPartEntity {
    
    
    public UploadImagePayload(ProgressListener listener, String imageFileUrl) {
        super(HttpMultipartMode.STRICT, listener);
    
        this.addPart("image", new FileBody(new File(imageFileUrl)));
        this.setStringPart("type", "file");
    }
    
    public void setAlbumId(String albumId) {
        this.setStringPart("album_id", albumId);
    }
    
    public void setName(String name) {
        this.setStringPart("name", name);
    }
    
    public void setTitle(String title) {
        this.setStringPart("title", title);
    }
    
    public void setDescription(String description) {
        this.setStringPart("description", description);
    }
    
    private void setStringPart(String name, String value) {
        try {
            addPart(name, new StringBody(value));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            Log.e(TAG, "unable to set string property on image upload");
        }
    }
    }
    

    Then just create an instance of the above class and set the data to it:

        myEntity.addPart("image", new FileBody(new File(imageFileUrl)));
        myEntity.setStringPart("type", "file");
    

    To send the request, just create an HTTPPost, and set the payload to your entity:

        HttpPost post = new HttpPost(requestUrl);
        post.setEntity(myEntity);
        HttpClient client = new DefaultHttpClient();
        client.execute(post);
    

    Using the above is fairly simple, and it is really easy to add progress listening to by just adding more logic by extending MultiPartEntiy, for example:

    public class BigMultiPartEntity extends MultipartEntity {
    
    private ProgressListener listener;
    
    public BigMultiPartEntity(final HttpMultipartMode mode, final ProgressListener listener)
    {
        super(mode);
        this.listener = listener;
    }
    
    public BigMultiPartEntity(HttpMultipartMode mode, final String boundary, final Charset charset, final ProgressListener listener)
    {
        super(mode, boundary, charset);
        this.listener = listener;
    }
    
    @Override
    public void writeTo(final OutputStream outstream) throws IOException
    {
        super.writeTo(new CountingOutputStream(outstream, this.listener));
    }
    
    public interface ProgressListener {
        void transferred(int num);
    }
    
    public class CountingOutputStream extends FilterOutputStream
    {
        private ProgressListener listener;
        private int transfered;
    
        /**
         * Creates an output stream filter built on top of the specified
         * underlying output stream.
         *
         * @param out the underlying output stream to be assigned to
         *            the field <tt>this.out</tt> for later use, or
         *            <code>null</code> if this instance is to be
         *            created without an underlying stream.
         */
        public CountingOutputStream(OutputStream out, ProgressListener listener) {
            super(out);
            this.listener = listener;
            this.transfered = 0;
        }
    
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            this.transfered += len;
            //Log.d(TAG, "writing...transfer @ "+transfered);
            this.listener.transferred((int) ((transfered / (float) getContentLength()) * 100));
            out.write(b, off, len);
    
    
        }
    
        @Override
        public void write(int b) throws IOException {
            this.transfered += b;
            //Log.d(TAG, "writing...transfer @ "+transfered);
            this.listener.transferred((int) ((transfered / (float) getContentLength()) * 100));
            out.write(b);
        }
    }
    }
    

    If you are not using Apache HTTPClient, and you are certainly wanting to use Base64, then have a look at: How to convert a image into Base64 string?

    If you need anymore help, check out the source code for my android imgur app located @ https://bitbucket.org/eggman87/ezimgur-open/src . The logic for talking to imgur is in the API project.