Использование ImageIO.read с URL перенаправления - PullRequest
1 голос
/ 31 января 2011

Я пытаюсь прочитать изображение из сети, используя ImageIO:

URL url = new URL(location);
bi = ImageIO.read(url);

Когда location - это URL, который заканчивается фактическим изображением (например, http://www.lol.net/1.jpg), приведенный выше код работает. Однако, когда URL является перенаправлением (например, http://www.lol.net/redirection,, ведущим к http://www.lol.net/1.jpg),, приведенный выше код возвращает null в bi .

Два вопроса. Во-первых, почему это происходит? Это происходит из-за того, что библиотека ImageIO пытается найти подходящий ImageReader на основе строки URL-адреса? И во-вторых, каким будет самое чистое решение этого ограничения? Обратите внимание, что ятребуется вывод BufferedImage , а не вывод Image .

EDIT : для тех, кто хочет это проверить, URL, который я пытаюсьчтение - http://graph.facebook.com/804672289/picture,, которое преобразуется в http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs351.snc4/41632_804672289_6662_q.jpg.

РЕДАКТИРОВАТЬ 2 : при последнем редактировании я ошибся. URL-адрес https://graph.facebook.com/804672289/picture. Если я заменилhttps с http, приведенный выше код работает нормально. Поэтому мой новый вопрос заключается в том, как заставить его работать с HTTPS, поэтому мне не нужно делатьзамена.

Ответы [ 4 ]

4 голосов
/ 12 сентября 2014

У меня была такая же проблема со ссылками на изображения https.Проблема заключалась в том, что когда я читал ссылку https в коде, она возвращала бы 200. Но на самом деле это была 301. Чтобы обойти эту проблему, я использовал user-agent "curl", чтобы получить301 и итерируйте, пока не найдете последнюю ссылку.См. Код ниже:

Надеюсь, это поможет @ Эльдад-Мор.

private InputStream getInputStream(String url) throws IOException {
        InputStream stream = null;
        try {
            stream = handleRedirects(url);
            byte[] bytes = IOUtils.toByteArray(stream);
            return new ByteArrayInputStream(bytes);
        } finally {
            if (stream != null)
                stream.close();
        }
    }

    /**
     * Handle redirects in the URL Manually. Method calls itself if redirects are found until there re no more redirects.
     * 
     * @param url URL
     * @return input stream
     * @throws IOException
     */
    private InputStream handleRedirects(String url) throws IOException {
        HttpURLConnection.setFollowRedirects(false);
        URL obj = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
        conn.setRequestProperty("User-Agent", "curl/7.30.0");
        conn.connect();
        boolean redirect = false;
        LOG.info(conn.getURL().toString());

        int status = conn.getResponseCode();
        if (status != HttpURLConnection.HTTP_OK) {
            if (status == HttpURLConnection.HTTP_MOVED_TEMP
                    || status == HttpURLConnection.HTTP_MOVED_PERM
                    || status == HttpURLConnection.HTTP_SEE_OTHER)
                redirect = true;
        }
        if (redirect) {
            String newUrl =conn.getHeaderField("Location");
            conn.getInputStream().close();
            conn.disconnect();
            return handleRedirects(newUrl);
        }
        return conn.getInputStream();
    }
4 голосов
/ 31 января 2011

Мне не кажется, что http://www.lol.net/1.jpg указывает непосредственно на изображение.

Как указывает @Bozho, ImageIO использует значение по умолчанию URL.openConnection, которое (поскольку адрес начинается с"http") возвращает HttpURLConnection, который по умолчанию имеет setFollowRedirects(true).

Что касается вашего редактирования , мне кажется, этот код работает нормально:

URL url = new URL("http://graph.facebook.com/804672289/picture");
BufferedImage bi = ImageIO.read(url);

System.out.println(bi);
// Prints: BufferedImage@43b09468: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@7ddf5a8f transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 50 height = 50 #numDataElements 3 dataOff[0] = 2

Я подозреваю, что ваша ошибка в другом месте.

2 голосов
/ 25 мая 2015

Относительно вашего РЕДАКТИРОВАНИЯ 2:

ImageIo.read (url), не заботится о типе URL. т.е. http или https.

Вы можете просто передать URL-адрес этому методу, но если вы передаете URL-адрес https, необходимо выполнить определенные шаги для проверки SSL-сертификата. Пожалуйста, найдите приведенный ниже пример.

1) Для http и https:

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.X509Certificate;
import javax.imageio.ImageIO;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;


/**
 * @author Syed CBE
 *
 */
public class Main {


    public static void main(String[] args) {

                int height = 0,width = 0;
                String imagePath="https://www.sampledomain.com/sampleimage.jpg";
                System.out.println("URL=="+imagePath);
                InputStream connection;
                try {
                    URL url = new URL(imagePath);  
                    if(imagePath.indexOf("https://")!=-1){
                        final SSLContext sc = SSLContext.getInstance("SSL");
                        sc.init(null, getTrustingManager(), new java.security.SecureRandom());                                 
                        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
                        connection = url.openStream();
                     }
                    else{
                        connection = url.openStream();
                    }
                    BufferedImage bufferedimage = ImageIO.read(connection);
                    width          = bufferedimage.getWidth();
                    height         = bufferedimage.getHeight();
                    System.out.println("width="+width);
                    System.out.println("height="+height);
                } catch (MalformedURLException e) {

                    System.out.println("URL is not correct : " + imagePath);
                } catch (IOException e) {

                    System.out.println("IOException Occurred : "+e);
                }
                catch (Exception e) {

                    System.out.println("Exception Occurred  : "+e);
                }


    }

     private static TrustManager[] getTrustingManager() {
            TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {

                   @Override
                   public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                         return null;
                   }

                   @Override
                   public void checkClientTrusted(X509Certificate[] certs, String authType) {
                   }

                   @Override
                   public void checkServerTrusted(X509Certificate[] certs, String authType) {
                   }
            } };
            return trustAllCerts;
     }

}

2) Только для http:

// This Code will work only for http, you can make it work for https but you need additional code to add SSL certificate using keystore
    public static void getImage(String testUrl) {

            String testUrl="https://sampleurl.com/image.jpg";

        HttpGet httpGet = new HttpGet(testUrl);
                 System.out.println("HttpGet is  ---->"+httpGet.getURI());
                HttpResponse httpResponse = null;
                HttpClient httpClient=new DefaultHttpClient();

                try {

                    httpResponse = httpClient.execute(httpGet);
                    InputStream stream=httpResponse.getEntity().getContent();
                     BufferedImage sourceImg = ImageIO.read(stream);
                    System.out.println("------ source -----"+sourceImg.getHeight());
                     sourceImg.getWidth();
                        System.out.println(sourceImg);
                }catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    System.out.println("------ MalformedURLException -----"+e);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                System.out.println("------  IOEXCEPTION -----"+e);
                }
    }
0 голосов
/ 19 апреля 2015

На данный момент Apache HttpClient может быть использован, для меня это прекрасно работает.

http://hc.apache.org/

    public static void main(String args[]) throws Exception{
    String url = "http://graph.facebook.com/804672289/picture?width=800";

    HttpClient client = HttpClients.createDefault();
    HttpResponse response = client.execute(new HttpGet(url));
    BufferedImage image = ImageIO.read(input);

    if(image == null){
        throw new RuntimeException("Ooops");
    } else{
        System.out.println(image.getHeight());
    }
}
...