Click here to view submission (112 lines)
Assuming you are getting the image from an http server, the best way to get the image is to create a URL object. This does it all for you. However, I suspect the person posing this question had more in mind, so here is a way to actually implement the http request; it can be modified for other protocols as appropriate. The technique is straigtforward: Create a socket, send the request in the format the server wants, listen for the reply and store it, and close the socket. Here is the code:
// Create a socket connection with the server Socket socket = new Socket(hostname, port); // Determine the socket's input and output stream handles DataInputStream dis = new DataInputStream(socket.getInputStream()); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); // Write CGI-formatted command to server, requesting the data dos.writeBytes("GET " + args[1] + " HTTP/1.0"); dos.write(0x0d); dos.write(0x0a); dos.write(0x0d); dos.write(0x0a); // Read the response, directly from the socket long MAXLENGTH = ...the largest size the file can be...; byte b[] = new byte[MAXLENGTH]; long c = dis.read(b, 0, MAXLENGTH); // Note: don't make MAXLENGTH larger than read() can handle; // you may want to add buffering to this algorithm. // Close the socket socket.close(); // The data we wanted is now stored in b[]. // (Note: I haven't checked this, but it should work; I've written // other similar things.)
This code is a simple modification of the example provided in the Java Tutorial form Sun. The only thing to modify is the text to submit when do you want to make a POST or a GET:(Submitted by Jean-Luc DELATRE)Steps to make the submission:
POST METHOD:
GET METHOD:
- Create the URL to the server CGI
- Open the connection
- Open type outputstream
- Create the output string with the format:
varname1=varvalue1&varname2=varvalue2 // and so on Note that the character '&' is the separator from variables.- Close the outputstream
- Open the input stream
- Read the response from the server
- Close the input stream.
Note: The GET method does not requires an outputstream.
- Create the URL to the server CGI with the diference: Example:
'www.pp.com/pp.cgi?'+the output string with the self format form the output string like the step 4 in the POST METHOD.- Open the connection
- Open the input stream
- Read the response from the server
- Close the input stream.
The following example is to submit a form with the POST method, I have tried with a lot of forms and it works well.
import java.io.*; import java.net.*; public class TestingTheForm { public static void main(String[] args) { try { URL url = new URL("TheURL"); System.err.println("URL created:" + url.toString()); URLConnection connection = url.openConnection(); System.err.println("URLConnection opened ..."); PrintStream outStream = new PrintStream(connection.getOutputStream()); System.err.println("outStream created ..."); outStream.println("var1=value1&var2=value2&var3=value3"); System.err.println("the data printed ..."); outStream.close(); System.err.println("outStream closed ..."); DataInputStream inStream = new DataInputStream(connection.getInputStream()); String inputLine; System.err.println("inStream opened ..."); while ((inputLine = inStream.readLine()) != null) { System.out.println(inputLine); } inStream.close(); System.err.println("inStream closed ..."); } catch (MalformedURLException me) { System.err.println("MalformedURLException: " + me); } catch (IOException ioe) { System.err.println("IOException: " + ioe); } } }
You don't need to mess around with sockets and the HTTP header to issue a POST you just need to provide the "Content-type" and "Content-length" this is an excerpt from a working applet of mine which can be seen at http://www.lga.jca.fr/dossier_web/jld/accueilcafe.html (all in french, sorry...) this however does NOT solve the long outstanding showDocument() problem (see http://www.tientien.com/tjn/post/index.html) which is the last question in your "CGI, Servers"(Submitted by Dennis M. Kowallek){ .../... if (! usePOST) { cgiUrl = new URL(getDocumentBase(), "cgi/bounce.cgi" + query); debugOut("translated url: " + cgiUrl.toExternalForm()); connect = cgiUrl.openConnection(); } else { cgiUrl = new URL(getDocumentBase(), "cgi/bounce.cgi"); debugOut("translated url: " + cgiUrl.toExternalForm()); connect = cgiUrl.openConnection(); connect.setDoInput(true); connect.setDoOutput(true); connect.setUseCaches(false); connect.setRequestProperty ("Content-type", "application/dont-know-what"); String request = "nom=" + name.getText() + " " + "email=" + email.getText() + " " + "options=" + options.getSelectedItem() + " " + "\r\n"; connect.setRequestProperty ("Content-length", Integer.toString(request.length())); outStream = new DataOutputStream(connect.getOutputStream()); outStream.writeBytes(request); } DataInputStream inStream = new DataInputStream(connect.getInputStream()); debugOut("Content " + connect.getContentType() + " length " + Integer.toString(connect.getContentLength())); while ((inputLine = inStream.readLine()) != null) { debugOut(inputLine); } if (usePOST) outStream.close(); inStream.close(); }
The following is from a POST on "comp.lang.java" by Ronald.Tschalaer@psi.ch. I tried it and it works!(Submitted by Luc Snels)This is probably more an http question, but basically all you need to do is create a header of the form:
POST cgi-script HTTP/1.0Content-type: Content-length: The data you're posting... Here is a simple java applet which will contact my_script.cgi, post it the stuff in sdata, and read in the reply into rdata and display it.
PostExample.java: ----------------- import java.applet.Applet; import java.awt.*; import java.net.*; import java.io.*; import java.util.*; public class PostExample extends Applet { private final String script = "/cgi-bin/my_script.cgi"; private final String ctype = "application/octet-stream"; // note: on some servers this needs to be "application/x-www-form-urlencoded" // - Courtesy, John Fallows private String sdata = "Hello World"; private String rdata = ""; private String home; private int port; public void init() { home = getDocumentBase().getHost(); port = getDocumentBase().getPort(); if (port == -1) port = 80; } public void start() { Socket sock; OutputStream outp; InputStream inp; DataOutputStream dataout; DataInputStream datain; rdata = ""; //create a client socket try sock = new Socket(home, port); catch (Exception e) { rdata = e+" (socket: Host: "+home+"\tPort: "+port+")"; return; } // Obtain output stream to communicate with the server try { outp = sock.getOutputStream(); inp = sock.getInputStream(); } catch (Exception e) { rdata = e+" (getstream)"; try sock.close(); catch (IOException ee) ; return; } try { dataout = new DataOutputStream(outp); datain = new DataInputStream(inp); } catch (Exception e) { rdata = e+" (Dstream)"; try sock.close(); catch (IOException ee) ; return; } // Send http request to server and get return data try { // HTTP header dataout.writeBytes("POST " + script + " HTTP/1.0\r\n"); dataout.writeBytes("Content-type: " + ctype + "\r\n"); dataout.writeBytes("Content-length: " + sdata.length() + "\r\n"); dataout.writeBytes("\r\n"); // end of header // POST data dataout.writeBytes(sdata); dataout.writeBytes("\r\n"); boolean body = false; String line; while ((line = datain.readLine()) != null) { if (body) rdata += "\n" + line; else if (line.equals("")) // end of header body = true; } } catch (Exception e) { rdata = e+" (write)"; try sock.close(); catch (IOException ee) ; return; } // close up shop try { dataout.close(); datain.close(); } catch (IOException e) ; try sock.close(); catch (IOException e) ; } public void stop() {} public void paint(Graphics g) { StringTokenizer st = new StringTokenizer(rdata, "\n"); int line = 1, line_sp = getFontMetrics(getFont()).getHeight()+1; while (st.hasMoreTokens()) { g.drawString(st.nextToken(), 5, line*line_sp); line++; } } }
If you use the previous method with 16-bit char data (i.e. the upper 8 bits of a char are not zero) sustitute your "dataout.writeBytes()" with this "sendString()" method:void sendString(String x){ byte bytes[]=new byte[x.length()]; x.getBytes(0,x.length(),bytes,0); try for (int i=0; i < x.length(); i++) dataout.writeByte(bytes[i]); catch(Exception e); }
A related question...
"Also, whenever I run a CGI script that generates a document, no applets run from that document, presumably because the document directory changes, but I see no way of changing it back..."Just make sure the CODEBASE attribute in the APPLET tag points to the directory in which the applet sits, then it works fine (either use an absolute path, or remember that the path will be relative to the directory the cgi-script resides in (usually /cgi-bin) ). - Ronals McNulty
"This needs an encoded password and username (base64) and the ability to support the http authentication protocol extensions."
/*************************************************************************** If you need to provide basic authentication information, you have to send the WWW Server the following line (at least!) Authorization: Basic auth_info where auth_info is the string "username:password" encoded in the Base64 Printable Encoding format. I rewrote the WWW "HTUU.C" encode function in Java. I believe you do not need any other packages (except java.lang). Usage: String auth_info = HTUU.encode("username:password"); *****************************************************************************/ /* ** HTUU.CLASS ** ** ACKNOWLEDGEMENT: ** Main code is taken from the HTUU.C distribution, and was originally ** written by Mark Riordan (riordanmr@clvax1.cl.msu.edu) ** and Ari Luotonen (luotonen@dxcern.cern.ch). ** ** AUTHORS: ** IG Ian Goh ian.goh@jhu.edu ** ** HISTORY: ** Converted HTUU.C "HTUU_encode" function into Java (1.0.2): IG 13 July 1996 ** ------------------------------------------------------------- ** File contains a routine to convert a buffer ** of bytes to RFC 1113 printable encoding format. ** ** This technique is similar to the familiar Unix uuencode ** format in that it maps 6 binary bits to one ASCII ** character (or more aptly, 3 binary bytes to 4 ASCII ** characters). However, RFC 1113 does not use the same ** mapping to printable characters as uuencode. ** ** Mark Riordan 12 August 1990 and 17 Feb 1991. ** This code is hereby placed in the public domain. ** ------------------------------------------------------------- ** ** */ class HTUU { static String version = "HTUU Class v1.0 7/13/96"; // the Base64 printable encoding characters static char[] ENC = { 'A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 'a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', '0','1','2','3','4','5','6','7','8','9','+','/' }; // function encode takes the "username:password" string and // converts it into the printable encoding format static String encode(String string) { int i, j; byte[] byte_array = new byte[3]; StringBuffer buf_coded = new StringBuffer(); // get length of input string int nbytes = string.length(); for (i = 0; i < nbytes; i+= 3) { // check to make sure we don't run off the end of input string if (i + 3 < nbytes) j = i + 3; else j = nbytes; string.getBytes(i, j, byte_array, 0); // get bytes i..j if (j - i == 1) { // missing last two bytes byte_array[1] = 0; byte_array[2] = 0; } if (j - i == 2) { // missing last byte byte_array[2] = 0; } // convert the three bytes into four Base64 characters // and append to the buf_coded string buffer buf_coded.append(ENC[byte_array[0] >> 2]); buf_coded.append(ENC[((byte_array[0] << 4) & 060) | ((byte_array[1] >> 4) & 017)]); buf_coded.append(ENC[((byte_array[1] << 2) & 074) | ((byte_array[2] >> 6) & 03)]); buf_coded.append(ENC[byte_array[2] & 077]); } // end for loop // If nbytes was not a multiple of 3, then we have encoded too // many characters. Adjust appropriately. int buf_length = buf_coded.length(); if (i == nbytes+1) { /* There were only 2 bytes in that last group */ buf_coded.setCharAt(buf_length - 1, '='); } else if (i == nbytes+2) { /* There was only 1 byte in that last group */ buf_coded.setCharAt(buf_length - 1, '='); buf_coded.setCharAt(buf_length - 2, '='); } // return the Base64 encoded string return buf_coded.toString(); } // end String encode (String) } // end Class HTUU
Check out GUESTBOOK.JAVA, or GEODETIC.JAVA, both at http://www.nai.net/~rvdi/home.htm. Source code is at http://www.nai.net/~rvdi/guestbook.java (or geodetic.java).
Click here to see Pat's code! (607 lines)(Submitted by Fields Marshall)
Visit http://ogi.com:420/java for a documented example on how to do this ..
There is the Jigsaw HTTP server written in Java from the World Wide Web (W3) Consortium avaiable at http://www.w3.org/pub/WWW/Jigsaw/(Submitted by Carl Davis)Please note that I am not afilliated with the W3 Consortium. I am just reporting Jigsaw's existence.
There is a freeware HTTP server written in Java at: http://www.vpro.nl/interaktief/java/beta/httpd/sources.html.(Submitted by Chuck Russell)
There is a commercially available HTTP server available in Java. ExpressO can be found at: http://www.capitalcity.com:4321. ExpressO can be purchased with our without a source code license.
Here is an example of a client-side image map program. (It is quickly hacked together, and I have not even compiled it, much less tried it; but it should work! Send me any comments. -CJB/** * A Class to map rectangular image regions to a list of URL's. */ class MyURLList { /** * The rectangular areas */ Rectangle rects[] = { // Create two side-by-side rectangles new Rectangle(0, 0, 20, 20), new Rectangle(20, 0, 20, 20) } /** * The associated URL's */ URL urls[] = { // Associate a URL with each rectangular region new URL("http://www.somewhere.com/xyz.html"), new URL("http://www.anywhere.edu/~anybody/home.htm") } /** * Method for performing the mapping */ public URL map(int x, int y) { for (int i = 0; i < rects.length; i++) { if (rects[i].inside(x, y)) return urls[i]; } return null; } } /** * A canvas to server as the image to be mapped */ class MyCanvas extends Canvas { MyURLList urlList; Applet applet; // the (top level) applet loaded by the browser /** * Construct the canvas */ public MyCanvas(MyURLList u, Applet a) { urlList = u; applet = a; resize(40, 20); } /** * Catch image click events */ public boolean handleEvent(Event e) { if (e.id == Event.MOUSE_DOWN) { // get the coordinates, and map them to a URL... URL url = urlList.map(e.x, e.y); // get the new HTML page if (url != null) applet.getAppletContext().showDocument(url); return true; } return super.handleEvent(e); } } /** * The applet to be loaded by the browser */ public class MyApplet extends Applet { public MyApplet() { MyURLList urlList = new MyURLList(); add(new MyCanvas(urlList, this)); } }