package com.qiniu.qiniulab.utils; import android.content.Context; import com.nostra13.universalimageloader.core.assist.ContentLengthInputStream; import com.nostra13.universalimageloader.core.download.BaseImageDownloader; import com.nostra13.universalimageloader.utils.IoUtils; import com.qiniu.android.dns.DnsManager; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.URL; import java.net.UnknownHostException; /** * Created by bailong on 15/8/17. */ public class CommonImageDownloader extends BaseImageDownloader { private final DnsManager dns; public CommonImageDownloader(Context context, int connectTimeout, int readTimeout, DnsManager dns) { super(context, connectTimeout, readTimeout); this.dns = dns; } private static boolean serverError(HttpURLConnection conn) throws IOException { return conn.getResponseCode() / 100 == 5; } private static boolean validIP(String ip) { if (ip == null || ip.length() < 7 || ip.length() > 15) return false; if (ip.contains("-")) return false; try { int x = 0; int y = ip.indexOf('.'); if (y != -1 && Integer.parseInt(ip.substring(x, y)) > 255) return false; x = ip.indexOf('.', ++y); if (x != -1 && Integer.parseInt(ip.substring(y, x)) > 255) return false; y = ip.indexOf('.', ++x); return !(y != -1 && Integer.parseInt(ip.substring(x, y)) > 255 && Integer.parseInt(ip.substring(++y, ip.length() - 1)) > 255 && ip.charAt(ip.length() - 1) != '.'); } catch (NumberFormatException e) { return false; } } /** * Retrieves {@link InputStream} of image by URI (image is located in the network). * * @param imageUri Image URI * @param extra Auxiliary object which was passed to {@link DisplayImageOptions.Builder#extraForDownloader(Object) * DisplayImageOptions.extraForDownloader(Object)}; can be null * @return {@link InputStream} of image * @throws IOException if some I/O error occurs during network request or if no InputStream could be created for * URL. */ protected InputStream getStreamFromNetwork(String imageUri, Object extra) throws IOException { URL u = new URL(imageUri); String host = u.getHost(); String[] ips = resolveAddresses(host); IOException lastException = null; for (String ip : ips) { HttpURLConnection conn = createConnection(imageUri, extra); conn.setRequestProperty("Host", host); int redirectCount = 0; try { while (conn.getResponseCode() / 100 == 3 && redirectCount < MAX_REDIRECT_COUNT) { conn = createConnection(conn.getHeaderField("Location"), extra); redirectCount++; } } catch (IOException e) { lastException = e; continue; } InputStream imageStream; try { imageStream = conn.getInputStream(); } catch (IOException e) { // Read all data to allow reuse connection (http://bit.ly/1ad35PY) IoUtils.readAndCloseStream(conn.getErrorStream()); lastException = e; continue; } if (serverError(conn)) { lastException = new IOException("Image request failed with response code " + conn.getResponseCode()); continue; } if (!shouldBeProcessed(conn)) { IoUtils.closeSilently(imageStream); throw new IOException("Image request failed with response code " + conn.getResponseCode()); } return new ContentLengthInputStream(new BufferedInputStream(imageStream, BUFFER_SIZE), conn.getContentLength()); } if (lastException != null) { throw lastException; } else { throw new IOException("unexpect error"); } } private String replaceHost(String url, String host, String ip) { return url.replaceFirst(host, ip); } private String[] resolveAddresses(String domain) throws IOException { if (dns == null) { InetAddress[] addresses = InetAddress.getAllByName(domain); String[] x = new String[addresses.length]; for (int i = 0; i < addresses.length; i++) { x[i] = addresses[i].getHostAddress(); } return x; } try { return dns.query(domain); } catch (IOException e) { throw new UnknownHostException(e.getMessage()); } } }