问题
I'm tring to upload from my Java local application an object that will include a file to a server. My plan is that a servlet running on tomcat will get the object using the ObjectInputStream
in the doGet
method. But I get an EOFE
xception`.
Here is the client code
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream("c:\\rafi.txt");
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int n = 0;
while (-1 != (n = inputStream.read(buffer))) {
output.write(buffer, 0, n);
}
inputStream.close();
File2 c2 = new File2(buffer);
URL url = new URL("http://localhost:8080/servertest/Server");
URLConnection cnx = url.openConnection();
cnx.setDoInput(true);
cnx.setDoOutput(true);
cnx.setRequestProperty("Content-Type", "application/octet-stream");
InputStream in = cnx.getInputStream();
OutputStream out = cnx.getOutputStream();
cnx.connect();
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(c2);
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(in);
boolean readBoolean = ois.readBoolean();
System.out.println(readBoolean);
ois.close();
in.close();
out.close();
}
}
here is the server's servlet
import java.io.*;
import javax.servlet.*;
@WebServlet("/Server")
public class Server extends HttpServlet {
private static final long serialVersionUID = 1L;
public Server() {
super();
}
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
InputStream in = req.getInputStream();
OutputStream out = res.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
ObjectInputStream ois = new ObjectInputStream(in);
File2 data_in;
try {
data_in = (File2) ois.readObject();
byte[] a = new byte[data_in.mybytearray.length];
System.arraycopy(data_in.mybytearray, 0, a, 0,data_in.mybytearray.length);
System.out.println(a.toString());
oos.writeBoolean(true);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
oos.writeBoolean(false);
}
finally{
oos.close();
}
res.setContentType("java-internal/" + File2.class.getName());
in.close();
}
}
When I debug the server side and run the client I get the exception in this row
ObjectOutputStream oos = new ObjectOutputStream(out);
This is the error I get
SEVERE: Servlet.service() for servlet [test1.Server] in context with path [/servertest] threw exception
java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at test1.Server.doGet(Server.java:38)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I saw this question, but i't didn't help me. I'm using tomcat 7.
回答1:
InputStream in = cnx.getInputStream();
OutputStream out = cnx.getOutputStream();
The URLConnection#getInputStream()
will immediately send the HTTP request to the server in order to retrieve the response body. The way as you've written the code, this thus takes place before you've written any bit to the HTTP request body. Hence the EOFException
on the server side.
You need to ask for the HTTP response body by URLConnection#getInputStream()
after you've written the necessary data to the HTTP request body. Here's a rewrite:
URLConnection connection = new URL("http://localhost:8080/servertest/Server").openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/octet-stream");
ObjectOutputStream oos = new ObjectOutputStream(connection.getOutputStream());
oos.writeObject(c2);
oos.close();
ObjectInputStream ois = new ObjectInputStream(connection.getInputStream());
boolean readBoolean = ois.readBoolean();
ois.close();
System.out.println(readBoolean);
Also, since you're basically sending a HTTP POST request, you need to handle this in the servlet's doPost()
method rather than the doGet()
method.
Unrelated to the concrete problem: this isn't really the best way of sending files over HTTP. While it might work, this is very tight coupled to Java serialization mechanism. I'd suggest to send HTTP multipart/form-data
requests instead. This can be achieved by Apache HttpComponents Client on the client side and Apache Commons FileUpload on the server side. This way the servlet is reuseable for other purposes, such as a HTML form with <input type="file">
in the front. Also the client can this way be reused to upload files to other HTTP websites.
回答2:
I solved this pbm with on client side :
HttpURLConnection cnx = (HttpURLConnection) new URL("http://localhost:8080/web").openConnection();
cnx.setRequestMethod("PUT");
来源:https://stackoverflow.com/questions/6036622/java-io-eofexception-when-sending-serialized-data-to-a-servlet