使用servlet将文件从服务器上传到客户端

时间:2011-01-09 00:05:49

标签: java sockets servlets network-programming

我正在尝试编写一个servlet,它可以将文件从客户端上传到服务器,并将文件从服务器下载到客户端,从特定位置到特定位置。但是有两个问题阻止了我: 1.将文件从客户端上传到服务器时,如何告诉服务器存储文件的位置? 2.(更重要的)如何从服务器下载到客户端部分?

以下是目前的代码:

import java.io.FileOutputStream;  
import java.io.ObjectInputStream;  
import java.io.ObjectOutputStream;  
import java.net.ServerSocket;  
import java.net.Socket;  

 public class Server extends Thread {  
   public static final int PORT = 3333;  
   public static final int BUFFER_SIZE = 100;  

 @Override  
 public void run() {  
     try {  
         ServerSocket serverSocket = new ServerSocket(PORT);  
         while (true) {  
             Socket s = serverSocket.accept();  
             saveFile(s);  
         }  
     } catch (Exception e) {  
         e.printStackTrace();  
     }  
 }  

 private void saveFile(Socket socket) throws Exception {  
     ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());  
     ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());  
     FileOutputStream fos = null;  
     byte [] buffer = new byte[BUFFER_SIZE];    
     Object o = ois.readObject();  

     if (o instanceof String) {  
         fos = new FileOutputStream(o.toString());  
     } else {  
         throwException(null);  
     }  
     Integer bytesRead = 0;  

     do {  
         o = ois.readObject();  

         if (!(o instanceof Integer)) {  
             throwException(null);  
         }  

         bytesRead = (Integer)o;  

         o = ois.readObject();  

         if (!(o instanceof byte[])) {  
             throwException(null);  
         }  

         buffer = (byte[]) o;   
         fos.write(buffer, 0, bytesRead);  
     } while (bytesRead == BUFFER_SIZE);  

     fos.close();  

     ois.close();  
     oos.close();  
 }  

 public static void throwException(String message) throws Exception {  
     throw new Exception(message);  
 }  

 public static void main(String[] args) {  
     new Server().start();  
 }  

}

package com.filetransfer.web;
import java.io.*;
import java.net.Socket;
import java.util.Arrays;
import javax.servlet.*;
import javax.servlet.http.*;

public class FileTransfer extends HttpServlet {

private static final long serialVersionUID = 1L;
public static final int PORT = 3333;  
public static final int BUFFER_SIZE = 100; 
public static final String HOST = "localhost";

public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    String action = request.getParameter("option");
    System.out.println(action);
    if ("upload".equals(action)) {
        uploadFile(request);
    } else if ("download".equals(action)) {
        downloadFile(request, response);
    }
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    doGet(request, response);
}
public void reportError(HttpServletResponse response, String message) throws IOException {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
}

public void uploadFile(HttpServletRequest request) {

    String fileLocation = request.getParameter("localfile");
    File file = new File(fileLocation);

    Socket socket;
    try {
        socket = new Socket(HOST, PORT);
        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());  
        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());  

        oos.writeObject(file.getName());  

        FileInputStream fis = new FileInputStream(file);  
        byte [] buffer = new byte[BUFFER_SIZE];  
        Integer bytesRead = 0;  

        while ((bytesRead = fis.read(buffer)) > 0) {  
            oos.writeObject(bytesRead);  
            oos.writeObject(Arrays.copyOf(buffer, buffer.length));  
        }  

        oos.close();  
        ois.close();

    }  catch (Exception e) {
        e.printStackTrace();
    }  
}


 public void downloadFile(HttpServletRequest request, HttpServletResponse response) {

        File file = new File(request.getParameter("remotefile"));
        Socket socket;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            socket = new Socket(HOST, PORT);
            response.setContentLength((int)file.length());
            outputStream = response.getOutputStream();
            inputStream = new BufferedInputStream(new FileInputStream(file));
            int nextByte;
            while ((nextByte = inputStream.read()) != -1) {
                outputStream.write(nextByte);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

1 个答案:

答案 0 :(得分:5)

由于您使用的是 HTTP servlet,因此我强烈建议您使用 HTTP 客户端。不要绕过专有和自我发明的请求/响应格式,而只是根据HTTP协议构建请求和响应。如果您遵守某种传输标准,那么毫无疑问,有几种可用的API和工具可以简化工作。

在客户端,您可以使用java.net.URLConnectionApache HttpClient。通过HTTP从客户端发送文件到服务器(上传)通常需要multipart/form-data请求编码。通过HTTP从服务器发送文件到客户端(下载)通常只需要一个正确的Content-Type标题和整个文件作为响应主体。

this answer的底部,您可以找到一个示例,说明如何通过URLConnection上传文件(以this answer为例,使用Apache HttpClient 4)。在this answer中,您可以找到如何在servlet中处理上载文件的示例。保存上传的文件很简单:只需将获得的InputStream写入某些FileOutputStream即可。在this article中,您可以找到如何发送文件以供下载的示例。保存下载的文件也很简单,只需将URLConnection#getInputStream()写入某些FileOutputStream