Ming Leung
Ming Leung

Reputation: 385

doPost servlet fail to return a valid bitmap, extra bits are added to the head of the file

In doPost, return the bitmap.

            String mimeType = sc.getMimeType(filename);
            // Set content type
            resp.setContentType(mimeType);
            // Set content size
            File file = new File(filename);
            resp.setContentLength((int)file.length());

            // Open the file and output streams
            FileInputStream in = new FileInputStream(file);
            // Copy the contents of the file to the output stream
            byte[] buf = new byte[1024];
            int count = 0;
            while ((count = in.read(buf)) >= 0) {
                outStream.write(buf, 0, count);
            }

From debugger, I have checked the byte[] buf, it is the same as the file.

On the client side, it is an android apps

        HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(_url);
        httpPost.setEntity(new UrlEncodedFormEntity(_nameValuePair));
        HttpResponse httpResponse = httpClient.execute(httpPost);                                      EntityUtils.getContentCharSet(httpResponse.getEntity());
        byte[] bytes = EntityUtils.toByteArray(httpResponse.getEntity());               
        Bitmap bitmap=BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

4 extra bytes, before the BM.P, are added to the head of the file. They are -84, -19, 0, 5. But the size of the array is the same as the original bmp file. The last 4 bytes of the original file are dropped.

So, BitmapFactory.decodeByteArray always fail to decode the bytes.

How can I serve the file on the server and how should I decode it on the android client correctly?

Upvotes: 0

Views: 68

Answers (1)

gaborsch
gaborsch

Reputation: 15758

Edit 2017.06.11:

As noted, the server side code pollutes the servlet outputstream. It is recommended to leave resp.setContentLength((int)file.length()); out, this will make sure that at least the full content is forwarded to the client.

The best way would be to remove the excess byte sequence somehow. Lacking that, the second code fragment below will ensure that the client will work with both garbaged and clean server output. Also, it is worth to mark the client code with a TODO, so this tweak would call attention later.


I think that if you checked the output on wire, and it was correct, then the bug should be on client side. Either way, if your Android code is faulty, you could work it around. I don't know the reason for the 4 extra bytes, but you could easily patch it this way:

Bitmap bitmap=BitmapFactory.decodeByteArray(bytes, 4, bytes.length-4);

I agree that the best way would be to know the reason, but sometimes it simply not worth. Otherwise you can play around with different BMPs, different sizes, different color depths, etc to find out what influences the content of the extra bytes.

If you want to stay on the safe side, you could look for the BM header:

int bmpOffset = 0;
while(bytes.length > bmpOffset+1 && (bytes[bmpOffset]!=0x42 || bytes[bmpOffset+1]!=0x4D))
    bmpOffset++;
}
Bitmap bitmap=BitmapFactory.decodeByteArray(bytes, bmpOffset, bytes.length-bmpOffset);  

This should work on all devices. Also, you could check if the file looks like a BMP or not.

Upvotes: 0

Related Questions