Java 使用带有重定向URL的ImageIO.read

Java 使用带有重定向URL的ImageIO.read,java,http,javax.imageio,jai,Java,Http,Javax.imageio,Jai,我正在尝试使用ImageIO从网络读取图像: URL url = new URL(location); bi = ImageIO.read(url); 当location是以实际图像结尾的URL时,例如,上面的代码可以工作。但是,当URL是重定向(例如,导致)时,上述代码在bi中返回null 两个问题。第一,为什么会这样?是否因为ImageIO库试图根据URL字符串找到合适的ImageReader?第二,对于这一限制,最干净的解决方案是什么?请注意,我需要BuffereImage输出,而不是图

我正在尝试使用ImageIO从网络读取图像:

URL url = new URL(location);
bi = ImageIO.read(url);
当location是以实际图像结尾的URL时,例如,上面的代码可以工作。但是,当URL是重定向(例如,导致)时,上述代码在bi中返回null

两个问题。第一,为什么会这样?是否因为ImageIO库试图根据URL字符串找到合适的ImageReader?第二,对于这一限制,最干净的解决方案是什么?请注意,我需要BuffereImage输出,而不是图像输出

编辑:对于任何想要测试它的人,我试图读取的URL是,它被转换为


编辑2:上次编辑时我不正确。网址是。如果我用http替换https,上面的代码可以正常工作。因此,我的新问题是如何使它与HTTPS一起工作,这样我就不需要进行替换。

对我来说,它似乎不像是直接指向图像

正如@Bozho所指出的,ImageIO使用默认的URL.openConnection,因为地址以http开头,所以它返回一个HttpURLConnection,默认情况下,该HttpURLConnection具有setFollowRedirectstrue

关于您的编辑,此代码对我来说似乎很好:

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

我怀疑你的错误在别的地方。

对我来说,这似乎不是直接指向图像

正如@Bozho所指出的,ImageIO使用默认的URL.openConnection,因为地址以http开头,所以它返回一个HttpURLConnection,默认情况下,该HttpURLConnection具有setFollowRedirectstrue

关于您的编辑,此代码对我来说似乎很好:

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

我怀疑您的错误在其他地方。

我在https图像链接方面也遇到了同样的问题。问题是,当我阅读代码中的https链接时,它会返回一个200。但实际上是301。为了解决这个问题,我使用了curl用户代理,以便获得301并迭代,直到找到最终链接。请参阅下面的代码:

希望这对@Eldad Mor有所帮助

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();
    }

我在使用https图像链接时也遇到了同样的问题。问题是,当我阅读代码中的https链接时,它会返回一个200。但实际上是301。为了解决这个问题,我使用了curl用户代理,以便获得301并迭代,直到找到最终链接。请参阅下面的代码:

希望这对@Eldad Mor有所帮助

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();
    }

目前可以使用ApacheHttpClient,对我来说它工作得很好


目前可以使用ApacheHttpClient,对我来说它工作得很好

关于编辑2:

ImageIo.readurl,不关心url类型。i、 例如,http或https

您可以简单地将url传递给此方法,但如果要传递https url,则需要执行某些步骤来验证SSL证书。请找到下面的例子

1对于http和https: 2仅对于http: 关于编辑2:

ImageIo.readurl,不关心url类型。i、 例如,http或https

您可以简单地将url传递给此方法,但如果要传递https url,则需要执行某些步骤来验证SSL证书。请找到下面的例子

1对于http和https: 2仅对于http:
这很奇怪。ImageIO使用默认的URL设置,其中包括followRedirects=trueI重定向URL也有相同的问题,只是每次调用ImageIO.readurl时,返回的图像每隔一次要么为null,要么不为null。这很奇怪。ImageIO使用默认URL设置,其中包括followRedirects=trueI重定向URL存在相同问题的变体,只是对于ImageIO.readurl的每次调用,每隔一次返回的图像要么为null,要么不为null。问题是我使用的URL是https://而不是http://。问题是为什么我看到的只是bi变为null,而不是一些错误——我如何在不使用http替换https的情况下克服这个问题。问题是我使用的URL是https://而不是http://。问题是为什么我看到的只是bi变为null,而不是一些错误——我如何在不使用http替换https的情况下克服这个问题。
// 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);
                }
    }