[英]Using ImageIO.read with a redirecting URL
我正在嘗試使用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 ),上述代碼在bi中返回null 。
兩個問題。 一,為什么會這樣? 是因為ImageIO庫試圖根據URL字符串找到合適的ImageReader嗎? 第二,什么是解決此限制的最佳方法? 請注意,我需要BufferedImage輸出而不是Image輸出。
編輯 :對於想測試它的人,我嘗試讀取的URL是http://graph.facebook.com/804672289/picture ,該URL轉換為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一起使用,因此我不需要進行替換。
我在使用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();
}
在我看來, 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:
ImageIo.read(url),不必理會url類型。 即http或https。
您可以簡單地將url傳遞給此方法,但是如果要傳遞https url,則需要執行某些步驟來驗證SSL證書。 請找到以下示例。
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;
}
}
// 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);
}
}
可以使用Apache HttpClient,對我來說它工作正常。
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());
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.