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

3

我正在尝试编写一个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个回答

5

由于您正在使用 HTTP servlet,我强烈建议您使用 HTTP 客户端。不要传递专有和自创的请求/响应格式,而是根据 HTTP 协议构造请求和响应。当您遵循某个传输标准时,就没有疑问会有几个可用的 API 和工具可以简化工作。

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

此答案底部,您可以找到一个使用URLConnection上传文件的示例(在此答案中有一个使用Apache HttpClient 4的示例)。在此答案中,您可以找到一个如何在servlet中处理上传文件的示例。保存上传的文件很容易:只需将获得的InputStream写入某个FileOutputStream即可。在此文章中,您可以找到一个发送文件进行下载的示例。保存下载的文件也很容易,只需将URLConnection#getInputStream()写入某个FileOutputStream即可。


3
BalusC在这里提出了非常重要的观点。没有必要重新发明轮子。 - rfeak
如果我想使用 URLConnection 下载一个在 URL 中指定了文件名的文件,那么可以这样做。但是我想从运行我的服务器的远程机器上下载一个随机的文件。 - brain_damage
你的具体问题是不知道如何让服务器返回一个随机文件? - BalusC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接