手头生正好有一个HTTP Client例子,使用socket 连接。代码如下:
import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; public class HTTPClient { public static void main(String[] args) { String uri = "/autofei/archive/2010/06/20/5681468.aspx"; int port = 80; String hostname = "blog.csdn.net"; try { InetAddress inetAdd = java.net.InetAddress.getByName(hostname); System.out.println("IP Address is : " + inetAdd.getHostAddress()); if (args.length != 0) { uri = args[0]; port = Integer.parseInt(args[1]); } String host = inetAdd.getHostAddress(); doGet(host, port, uri); } catch (java.net.UnknownHostException e) { e.printStackTrace(); } } public static void doGet(String host, int port, String uri) { Socket socket = null; try { socket = new Socket(host, port); } catch (Exception e) { e.printStackTrace(); } try { StringBuffer sb = new StringBuffer("GET " + uri + " HTTP/1.1/r/n"); sb.append("Accept: */*/r/n"); sb.append("Accept-Language: en/r/n"); sb.append("Accept-Encoding: gzip, deflate/r/n"); sb.append("User-Agent: HTTPClient/r/n"); sb.append("Host: " + host + " " + port + "/r/n"); sb.append("Connection: Keep-Alive/r/n/r/n"); OutputStream socketOut = socket.getOutputStream(); socketOut.write(sb.toString().getBytes()); Thread.sleep(2000); InputStream socketIn = socket.getInputStream(); int size = socketIn.available(); byte[] buffer = new byte[size]; socketIn.read(buffer); System.out.println(new String(buffer)); } catch (Exception e) { e.printStackTrace(); } finally { try { socket.close(); } catch (Exception e) { e.printStackTrace(); } } } }
运行上述代码,返回如下:
IP Address is : 211.100.26.77
HTTP/1.1 302 Moved Temporarily
Server: nginx/0.7.65
Date: Fri, 02 Jul 2010 14:27:19 GMT
Content-Type: text/html
Content-Length: 161
Connection: keep-alive
Location: http://www.csdn.net/
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx/0.7.65</center>
</body>
</html>
这个代码基本上是一个最原始的http clinet,模拟了http协议,比如协议头。但是这段代码有几个问题:
首先不能解析动态网页,如aspx等(不知道为什么,请知道的朋友告知,谢谢!)。
其次,服务器返回的是一个二进制byte[],你需要自己解析得到的你需要的内容。
因为我需要拿到的是一个二进制的png图片文件,并不关心头信息,如果能有一个library直接提供解析功能就好了。
Apache common HttpClient 库提供了很好的封装,因此非常简单的几行代码(不及异常处理)就可以了。
public static byte[] getImage(String id) { // Create an instance of HttpClient. HttpClient client = new HttpClient(); // Create a method instance. GetMethod method = new GetMethod( "http://hmdb.ca/labm/servlet/labm.mlims.show?ctrl=chemical_structure&hmdb_id=" + id); // Provide custom retry handler is necessary method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false)); try { // Execute the method. int statusCode = client.executeMethod(method); if (statusCode != HttpStatus.SC_OK) { System.err.println("Method failed: " + method.getStatusLine()); } // Read the response body. byte[] responseBody = method.getResponseBody(); return responseBody; } catch (HttpException e) { System.err.println("Fatal protocol violation: " + e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.err.println("Fatal transport error: " + e.getMessage()); e.printStackTrace(); } finally { // Release the connection. method.releaseConnection(); } return null; }
但是这个代码有时会给出如下警告:
Jul 2, 2010 11:42:34 AM org.apache.commons.httpclient.HttpMethodBase getResponseBody
WARNING: Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
按照提示应该使用getResponseBodyAsStream。其中最后还有一个将byte[]生成图片并显示,并且判断图片大小后,重新设置图片大小的。下面是我的完整实例:
import java.awt.Image; import java.awt.Toolkit; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.WindowConstants; import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpMethodParams; public class HTTPClient { public static byte[] getImage(String id) { // Create an instance of HttpClient. HttpClient client = new HttpClient(); // Create a method instance. GetMethod method = new GetMethod( "http://hmdb.ca/labm/servlet/labm.mlims.show?ctrl=chemical_structure&hmdb_id=" + id); // Provide custom retry handler is necessary method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false)); try { // Execute the method. int statusCode = client.executeMethod(method); if (statusCode != HttpStatus.SC_OK) { System.err.println("Method failed: " + method.getStatusLine()); } // Read the response body. // NOTE: cause warning for big file // byte[] responseBody = method.getResponseBody(); InputStream in = method.getResponseBodyAsStream(); ByteArrayOutputStream bAOut = new ByteArrayOutputStream(); int c; while ((c = in.read()) != -1) { bAOut.write(c); } return bAOut.toByteArray(); } catch (HttpException e) { System.err.println("Fatal protocol violation: " + e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.err.println("Fatal transport error: " + e.getMessage()); e.printStackTrace(); } finally { // Release the connection. method.releaseConnection(); } return null; } public static byte[] getBytesFromInputStream(InputStream is) throws IOException { // Get the size of the file long length = is.available(); System.out.println("length: " + length); if (length > Integer.MAX_VALUE) { // File is too large } // Create the byte array to hold the data byte[] bytes = new byte[(int) length]; // Read in the bytes int offset = 0; int numRead = 0; while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { offset += numRead; } // Ensure all the bytes have been read in if (offset < bytes.length) { throw new IOException("Could not completely read file "); } // Close the input stream and return bytes is.close(); return bytes; } public static void main(String[] args) { java.awt.Toolkit.getDefaultToolkit(); java.awt.Image image = Toolkit.getDefaultToolkit().createImage( getImage("HMDB00296")); // get image size int height = image.getHeight(null); int width = image.getWidth(null); // resize image size to fit screen if (height > 300) { image = image.getScaledInstance(width * 300 / height, 300, Image.SCALE_SMOOTH); } JFrame frame = new JFrame("Demo"); JPanel main = new JPanel(); JLabel pic = new JLabel("", new ImageIcon(image), JLabel.CENTER); main.add(pic); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setSize(800, 600); frame.getContentPane().add(main); frame.setVisible(true); } }
参考:
http://hc.apache.org/httpclient-3.x/tutorial.html
http://hc.apache.org/httpclient-3.x/apidocs/index.html