• No results found

Saving Files Using HTTP Post

If you don't want the overhead of JFS, you have some alternatives. You can take advantage of the existing classes that are able to post data to a Web server. Remember that when you post data to a Web server, you are essentially sending it a file. The only thing you have to do is create something to take the posted data and store it in a file. This turns out to be a trivial task under UNIX. The following shell script enables you to store data in a file:

#!/bin/sh

echo "Content-type: text/plain" echo

dd ibs=1 count=$CONTENT_LENGTH of=$QUERY_STRING 2>/dev/null echo $?

This script probably requires a bit of explanation. First of all, the filename that you are storing into is encoded in the URL and not in the posted data. If you were to call this script putfile and put it in the cgi-bin directory of your Web server, the following URL would try to post to a file called putme:

http://mywebhost/cgi-bin/putfile?putme

The shell script kicks into action by first printing response data that is required by every CGI program, namely the "Context- type" information. Next, it prints a blank line, signifying the end of the header information. Now comes the key to this script- the dd command. This command is similar to the cat command, except that it has the ability to read and write a fixed number of records. The ibs=1 option tells dd to use an input block size of 1 byte, meaning that the count option will tell how many bytes to read. Because the http server stores the number of bytes you posted in an environment variable called

CONTENT_LENGTH, you use this variable as the count parameter for dd. Finally, the of parameter is the name of the

output file you are writing to. Any error messages are sent to /dev/null, but the numeric exit code is printed as the final line of the response generated by the script. If the dd command is successful, the echo $? line will echo a 0.

Listing 8.2 shows a class that uses the POST command to send data to this script.

Listing 8.2 Source Code for PostPutFile.java

import java.net.*; import java.io.*;

// This class provides a static method to post a file to the // putfile script, which takes a filename as a parameter passed // in the POST request itself, and then receives the bytes as // the posted data.

public class PostPutFile extends Object {

Chapter 8 -- Reading and Writing Files from an Applet

// Put sends the named file to a specific URL. The URL should // contain the path name of the putfile script. This method // will append the ?filename to the script name.

// It returns 0 if the put was successful, or a non-zero number // if it failed for some reason.

public static int put(URL url, String filename, byte[] bytes) throws IOException, MalformedURLException

{

// Run the putfile script and ask it to store the data in a file called "putme" URL destURL = new URL(url.getProtocol(), url.getHost(),

url.getPort(), url.getFile()+"?"+filename); // Define the data that you want stored in the file.

URLConnection urlConn = destURL.openConnection(); urlConn.setDoOutput(true); // we need to write urlConn.setDoInput(true); // just to be safe...

urlConn.setUseCaches(false); // get info fresh from server // Tell the server what kind of data we are sending - in this case, // just a stream of bytes.

urlConn.setRequestProperty("Content-type", "application/octet-stream");

// Must tell the server the size of the data we are sending. This also // tells the URLConnection class that we are doing a POST instead

// of a GET.

urlConn.setRequestProperty("Content-length", ""+bytes.length); // Open an output stream so we can send the info we are posting

OutputStream outStream = urlConn.getOutputStream(); // Write out the actual request data

outStream.write(bytes); outStream.close();

// Now that we have sent the data, open up an input stream and get // the response back from the server

DataInputStream inStream = new DataInputStream( urlConn.getInputStream());

String line = inStream.readLine(); inStream.close();

Chapter 8 -- Reading and Writing Files from an Applet

try {

int result = Integer.valueOf(line).intValue(); return result;

} catch (Exception parseError) { return -1;

} } }

Listing 8.3 shows a simple example applet that stores a file using the PostPutFile class.

Listing 8.3 Source Code for TestPutFile.java

import java.net.*; import java.applet.*;

public class TestPutFile extends Applet {

public void init() {

try {

URL destURL = new URL(getDocumentBase(), "/cgi-bin/putfile");

// Define a string we want to send

String dataToSend = "This is a string that I want \n"+ "to store in the file.\n";

// The PostPutFile class wants a byte array, however, so we convert // the string to a byte array.

byte[] bytes = new byte[dataToSend.length()];

dataToSend.getBytes(0, dataToSend.length(), bytes, 0); PostPutFile.put(destURL, "/home/mark/putme", bytes); } catch (Exception e) { e.printStackTrace(); } } } Note

Chapter 8 -- Reading and Writing Files from an Applet

The new version of HTTP (HTTP 1.1) includes a PUT command that allows you to store a file without creating a separate CGI program to save the file. Some HTTP servers already support this new option. If you have a server that supports PUT and you want to save files from Java, you won't be able to use the URL class to send the file (until the URL class supports POST). You can, however, use the

PostSockURL class from Chapter 6 "Communicating with a Web Server," with a

little modification (change POST to PUT when it sends the HTTP command).