Java Network Programming (3rd ed) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Java Network Programming (3rd ed) [Electronic resources] - نسخه متنی

Harold, Elliotte Rusty

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








15.6 Writing Data to a Server


Sometimes you need to write data to a
URLConnectionfor example, when you submit a
form to a web server using POST or upload a file using PUT. The
getOutputStream() method returns an
OutputStream on which you can write data for
transmission to a server:

public OutputStream getOutputStream( )

Since a URLConnection doesn't
allow output by default, you have to call
setDoOutput(true) before asking for an output
stream. When you set doOutput to true for an
http URL, the request method is changed from GET
to POST. In Chapter 7, you saw how to send data
to server-side programs with GET.
However, GET should be limited to safe operations, such as search
requests or page navigation, and not used for unsafe operations that
create or modify a resource, such as posting a comment on a web page
or ordering a pizza. Safe operations can be bookmarked, cached,
spidered, prefetched, and so on. Unsafe operations should not be.

Once you've got the OutputStream,
buffer it by chaining it to a BufferedOutputStream
or a BufferedWriter. You should generally also
chain it to a DataOutputStream, an
OutputStreamWriter, or some other class
that's more convenient to use than a raw
OutputStream. For example:

try {
URL u = new URL("http://www.somehost.com/cgi-bin/acgi");
// open the connection and prepare it to POST
URLConnection uc = u.openConnection( );
uc.setDoOutput(true);
OutputStream raw = uc.getOutputStream( );
OutputStream buffered = new BufferedOutputStream(raw);
OutputStreamWriter out = new OutputStreamWriter(buffered, "8859_1");
out.write("first=Julie&middle=&last=Harting&work=String+Quartet\r\n");
out.flush( );
out.close( );
}
catch (IOException ex) {
System.err.println(ex);
}

Sending data with POST is almost as easy as with GET. Invoke
setDoOutput(true) and use the
URLConnection's
getOutputStream( ) method to write the query
string rather than attaching it to the URL. Java buffers all the data
written onto the output stream until the stream is closed. This is
necessary so that it can determine the necessary Content-length
header. The query string contains two name-value pairs separated by
ampersands. The complete transaction, including client request and
server response, looks something like this:

% telnet www.ibiblio.org 80
Trying 152.2.210.81...
Connected to www.ibiblio.org.
Escape character is '^]'.
POST /javafaq/books/jnp3/postquery.phtml HTTP/1.0
ACCEPT: text/plain
Content-type: application/x-www-form-urlencoded
Content-length: 65
username=Elliotte+Rusty+Harold&email=elharo%40metalab%2eunc%2eedu
HTTP/1.1 200 OK
Date: Mon, 10 May 2004 21:08:52 GMT
Server: Apache/1.3.29 (Unix) DAV/1.0.3 mod_perl/1.29 PHP/4.3.5
X-Powered-By: PHP/4.3.5
Connection: close
Content-Type: text/html
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Query Results</title>
</head>
<body>
<h1>Query Results</h1>
<p>You submitted the following name/value pairs:</p>
<ul>
<li>username = Elliotte Rusty Harold</li>
<li>email = elharo@metalab.unc.edu</li>
</ul>
<hr />
Last Modified May 10, 2004
</body>
</html>
Connection closed by foreign host.

For that matter, as long as you control both the client and the
server, you can use any other sort of data encoding you like. For
instance, SOAP and XML-RPC both POST data to web servers as XML
rather than an x-www-form-url-encoded query string. However, if you
deviate from the standard, you'll find that your
nonconforming client can't talk to most server-side
programs or that your nonconforming server-side program
can't process requests from most clients. The query
string format used here is used by all web browsers and is expected
by most server-side APIs and tools.

Example 15-8 is a program called
FormPoster that uses the
URLConnection class and the
QueryString class from Chapter 7 to post form data. The constructor sets the
URL. The query string is built using the add( )
method. The post( ) method actually sends the data
to the server by opening a URLConnection to the
specified URL, setting its doOutput field to
true, and writing the query string on the output
stream. It then returns the input stream containing the
server's response.

The main( ) method is a simple test for this
program that sends the name "Elliotte Rusty
Harold" and the email address
http://www.cafeaulait.org/books/jnp3/postquery.phtml.
This resource is a simple form tester that accepts any input using
either the POST or GET method and returns an HTML page showing the
names and values that were submitted. The data returned is HTML; this
example simply displays the HTML rather than attempting to parse it.
It would be easy to extend this program by adding a user interface
that lets you enter the name and email address to be postedbut
since doing that triples the size of the program while showing
nothing more of network programming, it is left as an exercise for
the reader. Once you understand this example, it should be easy to
write Java programs that communicate with other server-side scripts.


Example 15-8. Posting a form


import java.net.*;
import java.io.*;
import com.macfaq.net.*;
public class FormPoster {
private URL url;
// from Chapter 7, Example 7-9
private QueryString query = new QueryString( );
public FormPoster (URL url) {
if (!url.getProtocol( ).toLowerCase( ).startsWith("http")) {
throw new IllegalArgumentException(
"Posting only works for http URLs");
}
this.url = url;
}
public void add(String name, String value) {
query.add(name, value);
}
public URL getURL( ) {
return this.url;
}
public InputStream post( ) throws IOException {
// open the connection and prepare it to POST
URLConnection uc = url.openConnection( );
uc.setDoOutput(true);
OutputStreamWriter out
= new OutputStreamWriter(uc.getOutputStream( ), "ASCII");
// The POST line, the Content-type header,
// and the Content-length headers are sent by the URLConnection.
// We just need to send the data
out.write(query.toString( ));
out.write("\r\n");
out.flush( );
out.close( );
// Return the response
return uc.getInputStream( );
}
public static void main(String args[]) {
URL url;
if (args.length > 0) {
try {
url = new URL(args[0]);
}
catch (MalformedURLException ex) {
System.err.println("Usage: java FormPoster url");
return;
}
}
else {
try {
url = new URL(
"http://www.cafeaulait.org/books/jnp3/postquery.phtml");
}
catch (MalformedURLException ex) { // shouldn't happen
System.err.println(ex);
return;
}
}
FormPoster poster = new FormPoster(url);
poster.add("name", "Elliotte Rusty Harold");
poster.add("email", "elharo@metalab.unc.edu");
try {
InputStream in = poster.post( );
// Read the response
InputStreamReader r = new InputStreamReader(in);
int c;
while((c = r.read( )) != -1) {
System.out.print((char) c);
}
System.out.println( );
in.close( );
}
catch (IOException ex) {
System.err.println(ex);
}
}
}

Here's the response from the server:

% java -classpath .:jnp3e.jar FormPoster
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Query Results</title>
</head>
<body>
<h1>Query Results</h1>
<p>You submitted the following name/value pairs:</p>
<ul>
<li>name = Elliotte Rusty Harold</li>
<li>email = elharo@metalab.unc.edu
</li>
</ul>
<hr />
Last Modified May 10, 2004
</body>
</html>

The main( ) method tries to read the first
command-line argument from args[0]. The argument
is optional; if there is an argument, it is assumed to be a URL that
can be POSTed to. If there are no arguments, main() initializes url with a default URL,
http://www.cafeaulait.org/books/jnp3/postquery.phtml.
main( ) then constructs a
FormPoster object. Two name-value pairs are added
to this FormPoster object. Next, the
post( ) method is invoked and its response read
and printed on System.out.

The post( ) method
is the heart of the class. It first opens a connection to the URL
stored in the url field. It sets the
doOutput field of this connection to
true since this URLConnection
needs to send output and chains the OutputStream
for this URL to an ASCII OutputStreamWriter that
sends the data; then flushes and closes the stream. Do not
forget to close the stream! If the stream
isn't closed, no data will be sent. Finally, the
URLConnection's
InputStream is returned.

To summarize, posting data to a form requires these steps:

Decide what name-value pairs you'll send to the
server-side program.

Write the server-side program that will accept and process the
request. If it doesn't use any custom data encoding,
you can test this program using a regular HTML form and a web
browser.

Create a query string in your Java program. The string should look
like this:

name1=value1&name2=value2&name3=value3

Pass each name and value in the query string to
URLEncoder.encode( ) before adding it to the query
string.

Open a URLConnection to the URL of the program
that will accept the data.

Set doOutput to true by invoking
setDoOutput(true).

Write the query string onto the
URLConnection's
OutputStream.

Close the URLConnection's
OutputStream.

Read the server response from the
URLConnection's
InputStream.

Posting forms is considerably more complex than using the GET method
described in Chapter 7. However, GET should
only be used for safe operations that can be bookmarked and linked
to. POST should be used for unsafe operations that should not be
bookmarked or linked to.

The getOutputStream( ) method is also used for the
PUT request method, a means of storing files on a web server. The
data to be stored is written onto the OutputStream
that getOutputStream( ) returns. However, this can
be done only from within the HttpURLConnection
subclass of URLConnection, so discussion of PUT
will have to wait a little while.


/ 164