0

I'm trying to use avatars from http://avatars.adorable.io/ in my application. However, when trying to download for instance the following png: http://api.adorable.io/avatars/285/bla.png my HttpUrlConnection says it sees a content length of 0.

When I fiddle around in the browser I think I found the site uses some script to generate the avatar, and I think it might be on the client end. However, I'm not very knowledgeable about this and could not easily find an answer.

Would it be possible to download one of these avatars in a Java application using the following code?

private Pixmap syncDownloadPixmapFromURL(URL url) 
{   
    URLConnection conn;
    try 
    {
        conn = url.openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(false);
        conn.setUseCaches(true);
        conn.connect();
        int length = conn.getContentLength();
        if(length<=0) 
        {
            System.out.log("content length = 0!");
            return null;
        }
        InputStream is = conn.getInputStream();
        conn.setConnectTimeout(5000);
        DataInputStream dis = new DataInputStream(is);
        byte[] data = new byte[length];
        dis.readFully(data);
        dis.close();
        Pixmap pixmap = new Pixmap(data, 0, data.length);
        return pixmap;
    } 
    catch (MalformedURLException e) 
    {   
        e.printStackTrace();
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    }

    return null;
 }
p.streef
  • 3,652
  • 3
  • 26
  • 50
  • have you tried Volley NetworkImageView? http://101apps.co.za/index.php/articles/using-volley-to-download-cache-and-display-bitmaps.html – Rohan Pawar May 30 '16 at 06:12
  • I have not, but since I'm creating a libGDX game I don't want to use native android views. Also the code works fine for most images I try to download (the ones that report a content length at least). Might be interesting for another project I'm working on though! – p.streef May 30 '16 at 06:52

1 Answers1

1

This is because the server isn't sending a content length. It's not mandatory for a server to do that. As you mentioned, they use a script which is dynamically creating the content and writing the data "on the fly". They don't know the length of the data as they write the content to add it as a header.

Connection:keep-alive
Content-Type:image/png
Date:Mon, 30 May 2016 06:12:49 GMT
Expires:Mon Jun 06 2016 06:12:49 GMT+0000 (UTC)
Server:Cowboy
Transfer-Encoding:chunked
Via:1.1 vegur
X-Powered-By:Express

You could spool the stream into a ByteArrayOutputStream and then get the byte array from that.

Or you could use something like Apache Commons IO which has a method which handles this for you...

byte[] data = IOUtils.toByteArray(conn.getInputStream());

See this answer for other implementations: Convert InputStream to byte array in Java

Community
  • 1
  • 1
slipperyseal
  • 2,728
  • 1
  • 13
  • 15
  • IOUtils function looks useful, I will try it out and report my findings! – p.streef May 30 '16 at 06:55
  • Works perfectly, in stead of checking the length I can now just catch any errors from ioutils. Also, Less code = more better ;) – p.streef May 30 '16 at 07:46