2

首先,我的问题是关于 Java 中的 HttpServer 来处理来自客户端的 POST 请求,而不是关于可以将文件上传到 Web 服务器的 Java 客户端。

好的。我在 Java 中使用轻量级 HttpServer 来处理“GET”|| “POST”请求。HttpServer 的源代码复制自http://www.prasannatech.net/2008/11/http-web-server-java-post-file-upload.html

/*
 * HTTPPOSTServer.java
 * Author: S.Prasanna
 * @version 1.00 
 */

import java.io.*;
import java.net.*;
import java.util.*;

public class HTTPPOSTServer extends Thread {

    static final String HTML_START = 
        "<html>" +
        "<title>HTTP POST Server in java</title>" +
        "<body>";

    static final String HTML_END = 
        "</body>" +
        "</html>";

    Socket connectedClient = null;    
    BufferedReader inFromClient = null;
    DataOutputStream outToClient = null;


    public HTTPPOSTServer(Socket client) {
        connectedClient = client;
    }            

    public void run() {

        String currentLine = null, postBoundary = null, contentength = null, filename = null, contentLength = null;
        PrintWriter fout = null;

        try {

            System.out.println( "The Client "+
                    connectedClient.getInetAddress() + ":" + connectedClient.getPort() + " is connected");

            inFromClient = new BufferedReader(new InputStreamReader (connectedClient.getInputStream()));                  
            outToClient = new DataOutputStream(connectedClient.getOutputStream());

            currentLine = inFromClient.readLine();
            String headerLine = currentLine;                
            StringTokenizer tokenizer = new StringTokenizer(headerLine);
            String httpMethod = tokenizer.nextToken();
            String httpQueryString = tokenizer.nextToken();

            System.out.println(currentLine);

            if (httpMethod.equals("GET")) {    
                System.out.println("GET request");        
                if (httpQueryString.equals("/")) {
                    // The default home page
                    String responseString = HTTPPOSTServer.HTML_START + 
                        "<form action=\"http://127.0.0.1:5000\" enctype=\"multipart/form-data\"" +
                        "method=\"post\">" +
                        "Enter the name of the File <input name=\"file\" type=\"file\"><br>" +
                        "<input value=\"Upload\" type=\"submit\"></form>" +
                        "Upload only text files." +
                        HTTPPOSTServer.HTML_END;
                    sendResponse(200, responseString , false);                                
                } else {
                    sendResponse(404, "<b>The Requested resource not found ...." +
                            "Usage: http://127.0.0.1:5000</b>", false);                  
                }
            }
            else { //POST request
                System.out.println("POST request"); 
                do {
                    currentLine = inFromClient.readLine();

                    if (currentLine.indexOf("Content-Type: multipart/form-data") != -1) {
                        String boundary = currentLine.split("boundary=")[1];
                        // The POST boundary                           

                        while (true) {
                            currentLine = inFromClient.readLine();
                            if (currentLine.indexOf("Content-Length:") != -1) {
                                contentLength = currentLine.split(" ")[1];
                                System.out.println("Content Length = " + contentLength);
                                break;
                            }                      
                        }

                        //Content length should be < 2MB
                        if (Long.valueOf(contentLength) > 2000000L) {
                            sendResponse(200, "File size should be < 2MB", false);
                        }

                        while (true) {
                            currentLine = inFromClient.readLine();
                            if (currentLine.indexOf("--" + boundary) != -1) {
                                filename = inFromClient.readLine().split("filename=")[1].replaceAll("\"", "");                                        
                                String [] filelist = filename.split("\\" + System.getProperty("file.separator"));
                                filename = filelist[filelist.length - 1];                          
                                System.out.println("File to be uploaded = " + filename);
                                break;
                            }                      
                        }

                        String fileContentType = inFromClient.readLine().split(" ")[1];
                        System.out.println("File content type = " + fileContentType);

                        inFromClient.readLine(); //assert(inFromClient.readLine().equals("")) : "Expected line in POST request is "" ";

                        fout = new PrintWriter(filename);
                        String prevLine = inFromClient.readLine();
                        currentLine = inFromClient.readLine();              

                        //Here we upload the actual file contents
                        while (true) {
                            if (currentLine.equals("--" + boundary + "--")) {
                                fout.print(prevLine);
                                break;
                            }
                            else {
                                fout.println(prevLine);
                            }    
                            prevLine = currentLine;                      
                            currentLine = inFromClient.readLine();
                        }

                        sendResponse(200, "File " + filename + " Uploaded..", false);
                        fout.close();                   
                    } //if                                              
                }while (inFromClient.ready()); //End of do-while
            }//else
        } catch (Exception e) {
            e.printStackTrace();
        }    
    }

    public void sendResponse (int statusCode, String responseString, boolean isFile) throws Exception {

        String statusLine = null;
        String serverdetails = "Server: Java HTTPServer";
        String contentLengthLine = null;
        String fileName = null;        
        String contentTypeLine = "Content-Type: text/html" + "\r\n";
        FileInputStream fin = null;

        if (statusCode == 200)
            statusLine = "HTTP/1.1 200 OK" + "\r\n";
        else
            statusLine = "HTTP/1.1 404 Not Found" + "\r\n";    

        if (isFile) {
            fileName = responseString;            
            fin = new FileInputStream(fileName);
            contentLengthLine = "Content-Length: " + Integer.toString(fin.available()) + "\r\n";
            if (!fileName.endsWith(".htm") && !fileName.endsWith(".html"))
                contentTypeLine = "Content-Type: \r\n";    
        }                        
        else {
            responseString = HTTPPOSTServer.HTML_START + responseString + HTTPPOSTServer.HTML_END;
            contentLengthLine = "Content-Length: " + responseString.length() + "\r\n";    
        }            

        outToClient.writeBytes(statusLine);
        outToClient.writeBytes(serverdetails);
        outToClient.writeBytes(contentTypeLine);
        outToClient.writeBytes(contentLengthLine);
        outToClient.writeBytes("Connection: close\r\n");
        outToClient.writeBytes("\r\n");        

        if (isFile) sendFile(fin, outToClient);
        else outToClient.writeBytes(responseString);

        outToClient.close();
    }

    public void sendFile (FileInputStream fin, DataOutputStream out) throws Exception {
        byte[] buffer = new byte[1024] ;
        int bytesRead;

        while ((bytesRead = fin.read(buffer)) != -1 ) {
            out.write(buffer, 0, bytesRead);
        }
        fin.close();
    }

    public static void main (String args[]) throws Exception {

        ServerSocket Server = new ServerSocket (5000);         
        System.out.println ("HTTP Server Waiting for client on port 5000");

        while(true) {                                         
            Socket connected = Server.accept();
            (new HTTPPOSTServer(connected)).start();
        }      
    }
}

我通读了代码,我认为代码应该是可以的。

但是当我尝试上传文件时,它会打印出 POST 请求,然后挂在那里并且永远不会收到任何字节。

如果你愿意,你可以直接运行上面的源代码。启动它后,你可以在浏览器中输入 127.0.0.1:5000,它会显示文件上传,然后如果我尝试上传文件,它会在打印 PoST 请求后挂在那里。

如果你看代码很无聊,我可以问下面这个更简单的问题吗?

那么,Chrome 或任何其他网络浏览器究竟对 form -> input type='file' 做了什么?

如果我使用 ServerSocket 来处理 HTTP 请求,我只需获取请求的 InputStream,然后所有内容(包括 HTTP 标头和上传文件的内容)都会通过该 InputStream,对吗?

上面的代码可以分析标题,但似乎浏览器不再发送任何内容。

有人可以帮忙吗?

谢谢

4

3 回答 3

2

它挂起是因为客户端(在我的情况下是 Chrome)不提供Content-Length. RFC 1867对此非常模糊。它有点暗示它,但不强迫它,也没有一个例子。显然客户不会总是发送它。代码应防止丢失长度。相反,它会遍历循环,直到到达文件末尾。然后它挂起。

有时使用调试器很有帮助。

于 2011-07-23T02:32:11.620 回答
0

那是很多代码:)

让我们首先将break;调用移出 POST 部分内的 if 语句,从第 83 行开始。我们需要弄清楚什么是挂起的,而那些 while 语句很容易成为问题。

这将帮助我们找出问题所在。

如果你只是想让它工作,并不真正关心错误是什么,这有点像重新发明轮子,有大量的库可以使这成为一两行操作。

这是一个很好的: http ://www.servlets.com/cos/ - 查看MultiPartRequest课程(可下载源代码)

于 2011-07-23T02:44:42.543 回答
0

这是一个老问题,但万一其他人偶然发现它是为了寻找标题问题的答案,而不是细节中提到的特定错误(我觉得这是大多数观众的感觉)......我建议你省去痛苦并且不使用上面的代码片段。

它不是 HTTP 服务器,除了最简单的用例(显然即便如此)之外,它在任何情况下都会失败,也不会遵循基本的良好编码实践。即使不是这样,它也明确声明它只支持文本文件(并且确实将整个文件读入字符串),即使那样也不能正确处理字符集编码。

话虽如此,您可能在这里寻找两个答案之一 - 如何在应用程序中接受文件上传,或者 HTTP 服务器本身如何实现这一点。

如果您对如何出于娱乐或教育目的进行此操作感兴趣,我强烈建议您阅读 RFC(RFC 7230 用于核心 HTTP/1.1,RFC 2046 第 5.1 节用于多部分解析)并尝试编写一个简单的类似 HTTP 的服务器,例如这个。这是一种很好的学习方式,特别是如果您有经验丰富的开发人员来审查您的代码并为您提供提示并帮助您找到边缘案例。作为练习,您甚至可以从上面的代码开始,尝试修复它的缺点并使其更实用,不过,不要将其与用于生产的真实 HTTP 服务器混淆。

如果您不关心这一切,只想在实际应用程序中完成任务,我建议您只使用合适的 HTTP 服务器。周围有很多它们可以让你做上面的代码片段尝试做的事情,而代码和错误要少得多。

免责声明:我是JLHTTP - The Java Lightweight HTTP Server的作者,它是一个小型单文件服务器(或 ~50K/35K jar),没有依赖项,力求符合 RFC 并支持文件上传等。随意使用它,或者只是浏览代码和文档以获取一个相对简单的示例,说明 HTTP 服务器和多部分解析(文件上传)如何工作,既由服务器本身实现,又如何在应用程序中使用它。或者查看可以执行相同操作的许多其他 HTTP 服务器中的任何一个。

于 2018-06-03T19:57:01.850 回答