2010-02-13 23 views
1

我试图将URL中的JPEG图像保存为使用Java的文件。 URL:http://150.214.222.100//axis-cgi/mjpg/video.cgi?resolution=640x480&compression=1&duration=1&timeout=&dummy=garb如何将JPEG从URL保存到文件?

我尝试以下: 1)

Image image = fetchImage(urlNorthView); 

saveImage2Disk(image); 

public static Image fetchImage(URL u) throws MalformedURLException, IOException { 
     Toolkit tk = Toolkit.getDefaultToolkit(); 
     return tk.createImage(u); 
} 

private void saveImage2Disk(Image Image) throws IOException{ 
     File outputFile = new File("urlNorthView"+Calendar.getInstance().getTimeInMillis()+".jpg"); 

     BufferedImage bufferedImage = new BufferedImage(Image.getWidth(null),Image.getHeight(null), BufferedImage.TYPE_INT_RGB); 
     Graphics2D g2 = bufferedImage.createGraphics(); 
     g2.drawImage(Image, null, null); 
     ImageIO.write(bufferedImage, "jpg", outputFile); 
    } 

=>异常: “宽度(-1)和高度(-1)不能< = 0”

2 )

inputStream2Disk((InputStream) urlNorthView.getContent()); 

private void inputStream2Disk(InputStream in) throws Exception{ 
     File outputFile = new File("urlNorthView"+Calendar.getInstance().getTimeInMillis()+".jpg"); 
     OutputStream out=new FileOutputStream(outputFile); 
     byte buf[]=new byte[1024]; 
     int len; 
     while((len=in.read(buf))>0) 
     out.write(buf,0,len); 
     out.close(); 
     in.close(); 
    } 

该文件不知何故被破坏。当我与Kate打开它,我可以读:

--myboundary内容类型:图像/ JPEG内容长度:38256 ....

不应该有在任何文本二进制文件。

问题是什么?

+0

注意:第二种方法得到的是从URL中检索的* full *内容 - 包括标题,其中包含信息关于服务器发回的内容。 (通常,我们使用浏览器查看互联网上的项目,浏览器将解释标题以供自己使用,并仅向我们显示内容。) – Arkaaito 2010-02-13 09:09:43

+0

这些不是http标题,它们是mime标题。它们并不存在于绝大多数http响应中,但在这种情况下它们是http响应主体的一部分。请参阅下面的回复。如果您的浏览器使用给定的URL显示图像,这是因为它足够聪明来解析MIME部分。 – 2010-02-13 09:32:35

回答

2

由于某些原因,请求该图像时的http响应正文包含一个MIME部分(MIME部分对于将多个文件放入单个响应非常有用)。在这个回应中,只有一个MIME部分,所以它几乎是无用的。

javax.mail包中有代码,如果需要,您可能可以使用它来正确解析此代码,但它不是一个非常好的api,imho。

另外,有很多方法可以让你自己修改代码。由于只有一个MIME部分,所以您可以从输入流的开始处丢弃数据,直到您看到一行中有两个换行符(字节等于10)。这应该工作,因为MIME标题应该是7位ASCII,iirc,所以没有字符编码担心。

下面是一些示例代码:

URLConnection conn = urlNorthView.openConnection(); 
InputStream in = conn.getInputStream(); 
String contentType = conn.getHeaderField("Content-Type"); 
if (!"image/jpeg".equals(contentType)) { 
    // hack: assuming it's mime if not a raw image 
    int one = in.read(); 
    if (one == -1) { 
     // stop?? 
    } 
    int two = in.read(); 
    while (two != -1 && !(two == 10 && one == 10)) { 
     one = two; 
     two = in.read(); 
    } 
} 
// if it was mime, we've stripped off the mime headers 
// and should now get the image 
inputStream2Disk(in); 

编辑:废话,而不是两个\ -N,你会看到两个\ r \ n或字节0X0D,0X0A,0X0D,0X0A。丢弃数据,直到看到这种模式,这是留给读者的练习;)

+0

作品像一个魅力:) int two = in.read(); int three = in.read(); int four = in.read(); (two!= -1 &&!(one == 13 && two == 10 && three == 13 && four == 10)) \t \t one = two; \t \t two = three; \t \t三=四; \t \t four = in.read(); \t \t} – 2010-02-13 10:15:00

+0

@ M.R。不错,但是这个操作太低级了。你通常想避免这种情况。 – Bozho 2010-02-13 12:19:52

1

试试下面的方法,用于将ImageBufferedImage

private static BufferedImage getBufferedImage(Image img, int imageType) { 
    if (img instanceof BufferedImage) { 
     return (BufferedImage) img; 
    } 

    BufferedImage bi = new BufferedImage(img.getWidth(null), img 
      .getHeight(null), imageType); 

    Graphics2D g = (Graphics2D) bi.getGraphics(); 
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 

    g.drawImage(img, 0, 0, null); 
    g.dispose(); 

    return bi; 
} 

(其中imageType是宣布BufferedImage的一个常数。最有可能的TYPE_INT_RGB

否则,你的第一种方法是好的。

我会推荐第一个(高级别)方法,第二个(低级别)。

相关问题