java.io.EOFException when sending serialized data to a servlet

对着背影说爱祢 提交于 2020-01-24 12:54:08

问题


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 EOFException`.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!