如何让Java HttpServer处理文件上传的Post请求

发布于 2024-11-25 18:27:48 字数 9077 浏览 0 评论 0原文

首先,我的问题是关于 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 或任何其他网络浏览器到底对表单做了什么 ->输入类型='文件'?

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

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

有人可以帮忙吗?

谢谢

First of all, my question is about HttpServer in Java to handle the POST request from a client, not about a Java client who can upload file to a web server.

OK. I am using a lightweight HttpServer in Java to handle "GET" || "POST" requests. The source code of the HttpServer is copied from 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();
        }      
    }
}

I read through the code, I think the code should be all right.

But when I try to upload a file, it will print out POST request, and then hang there and never receive any bytes.

If you are willing to, you can run the above source code directly. After launch it, you can type 127.0.0.1:5000 in a browser, and it will show a file upload, then if I try upload a file, it will hang there after printing PoST request.

If you are bored to read the code, may I ask the following simpler question?

So, what exactly Chrome or any other web browser do about form -> input type='file'?

If I am using a ServerSocket to handle the HTTP request, I just get the InputStream of the request, and then all the content (including HTTP headers & the uploading file's content) will go through that InputStream, right?

The above code can analyse the headers, but then it seems nothing is sent from the browser any more.

Can anyone pls help?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蓝色星空 2024-12-02 18:27:48

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

使用调试器有时非常有帮助。

It hangs because client (Chrome, in my case) does not provide Content-Length.
RFC 1867 is pretty vague about it. It kind of suggests it but does not force it and does not have an example. Apparently clients would not always send it. The code should safeguard against missing length. Instead it goes through the loop until it reaches the end of file. Then it hangs.

Using debugger is very helpful at times.

嘿看小鸭子会跑 2024-12-02 18:27:48

这是很多代码 :)

让我们首先将 break; 调用移出 POST 部分内的 if 语句,从第 83 行开始。我们需要找出挂起的内容,而那些 while 语句可以轻松地成为问题。

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

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

这是一个很好的:http://www.servlets.com/cos/ - 看看 < code>MultiPartRequest 类(源代码可下载)

Thats a lotta code :)

Let start by moving the break; calls out of the if statements inside the POST section, starting with line 83. We need to figure out what is hanging and those while statements could easily be the issue.

This will help us figure out where the issue is.

If you just want it to work, and don't really care what the bug is, this is sort of re-inventing the wheel, there are a ton of libraries out there to make this a one or two line operation.

Here's a good one : http://www.servlets.com/cos/ - look at the MultiPartRequest class (source is available in download)

百思不得你姐 2024-12-02 18:27:48

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

它不是一个 HTTP 服务器,除了最简单的用例之外(显然即使如此),它也会失败,也不遵循基本的良好编码实践。即使不是这样,它也明确声明它仅支持文本文件(并且确实将整个文件读取到字符串中),即使这样也无法正确处理字符集编码。

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

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

如果您不关心所有这些,只想在实际应用程序中完成工作,我建议您仅使用适当的 HTTP 服务器。有很多这样的工具可以让你做上面代码片段尝试做的事情,而且代码和错误要少得多。

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

This is an old question, but in case others stumble upon it looking for an answer to the title question rather than the specific bug mentioned in the details (I have a feeling that's most viewers)... I would recommend you save yourself the pain and not use the above code snippet.

It is not an HTTP server and it will fail on any but the simplest use case (and apparently even then), nor does is follow basic good coding practices. Even if it weren't for that, it explicitly states it supports text files only (and indeed reads the whole file into a String), and even then doesn't properly handle charset encodings.

That being said, you're probably here looking for one of two answers - how you can accept file uploads in your application, or how an HTTP server itself implements this.

If you are interested in how to do this for fun or educational purposes, I do highly recommend reading the RFCs (RFC 7230 for core HTTP/1.1, RFC 2046 section 5.1 for multipart parsing) and trying to write a simple HTTP-like server like this one. It's a good way to learn, especially if you have an experienced developer to review your code and give you tips and help you find edge cases. As an exercise, you can even start with the code above and try to fix its shortcomings and make it a bit more usable, though still, don't confuse that with a real HTTP server for use in production.

If you don't care for all this and just want to get things done in a real application, I recommend just using a proper HTTP server. There are plenty of them around that will let you do what the above snippet tries to, with much less code and bugs.

Disclaimer: I'm the author of JLHTTP - The Java Lightweight HTTP Server which is a tiny one-file server (or ~50K/35K jar) with no dependencies that strives to be RFC-compliant and supports file uploads among other things. Feel free to use it, or just browse the code and documentation for a relatively simple example of how an HTTP server and multipart parsing (file uploads) might work, both as implemented by the server itself and how you can use this in your application. Or check out any of the many other HTTP servers out there that can do the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文