Java-сервер отправляет html-страницу из файла в браузер

Я пытался создать java-сервер, который отображает индекс из файла. Я создаю SocketServer и подключаю его к порту. Затем создайте Socket, выступающий в качестве клиента, и создайте PrintWriter, подключенный к выходному потоку сокета клиента. Все работает, если я жестко закодирую страницу в PrintWriter, но когда я пытаюсь прочитать файл построчно и отправить его в PrintWriter, ничего не отображается.

package com.github.masonnoyce;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Date;
import java.io.File;
import java.nio.file.Files;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.PrintWriter;


public class AServer
{
    public static void main (String[] args) throws Exception
    {
        AServer server = new AServer();
        int portNumber = 8080;
        //create server socket and say that it is running
        final ServerSocket myServer = new ServerSocket(portNumber);
        System.out.println("I have Connected To Port " + portNumber);

        boolean running = true;
        while(running)
        {
                //See if anyone connects
                try(Socket client = myServer.accept())
                {                    
                    server.sendPage(client);
                }
                catch(IOException e)
                {
                    System.out.println("Something went wrong streaming the page");
                    System.exit(1);
                }
        }
        try
        {
            myServer.close();
        }
        finally
        {
            System.out.println("Server Is now closed");
        }        
    }
    private void sendPage(Socket client) throws Exception
    {
        System.out.println("Page writter called");

        PrintWriter printWriter = new PrintWriter(client.getOutputStream());//Make a writer for the output stream to the client
        BufferedReader reader = new BufferedReader(new FileReader("path/to/index.html"));//grab a file and put it into the buffer
        String line = reader.readLine();//line to go line by line from file
        while(line != null)//repeat till the file is empty
        {
            printWriter.println(line);//print current line
            printWriter.flush();// I have also tried putting this outside the while loop right before 
            printWriter.close()
            line = reader.readLine();//read next line
        }
        reader.close();//close the reader
        printWriter.close();//Close the writer
//***********This section works if I replace the While loop With It**********//
//            printWriter.println("HTTP/1.1 200 OK");
//            printWriter.println("Content-Type: text/html");
//            printWriter.println("\r\n");
//            printWriter.println("<p> Hello world </p>");
//            printWriter.flush();//needed to actually send the data to the client
//            printWriter.close();//Close the writer
//************Above is the Hardcoding I was talking about****************************// 
    }    
} 

Теперь я знаю, что сервер должен работать в потоке, что он технически никогда не может выйти в данный момент и что некоторые импорты не нужны. Я не беспокоюсь об этом прямо сейчас. Мне просто нужно выяснить, почему PrintWriter не любит использовать файл, когда дело доходит до html, представленного в браузере. Я создал отладочный PrintWriter, который записывает в файл, чтобы проверить, есть ли у меня правильное расположение файла, и он работает с этим.


person Msnoyce    schedule 16.04.2020    source источник


Ответы (1)


Когда вы тестируете свой сервер с помощью веб-браузера, вам необходимо отправить действительный HTTP-запрос, включая заголовки HTTP, которые предоставлены в вашей жестко запрограммированной части.

Таким образом, вы должны просто добавить вывод части заголовка непосредственно перед печатью содержимого файла.

Также вам необходимо собрать информацию о размере файла и отправить заголовок "Content-Length: " + file_size + "\r\n".

Есть ошибка с закрытием printWriter до того, как вы закончите чтение файла подкачки, вам нужно закрыть его после цикла:

    while(line != null)//repeat till the file is empty
    {
        printWriter.println(line);//print current line
        printWriter.flush();// I have also tried putting this outside the while loop right before 
        printWriter.close() // BUG: no ";" and closing printWriter too early
        line = reader.readLine();//read next line
    }

Итак, обновленный метод отправки вашего файла клиенту выглядит следующим образом:

    private void sendPage(Socket client) throws Exception {
        System.out.println("Page writter called");

        File index = new File("index.html");

        PrintWriter printWriter = new PrintWriter(client.getOutputStream());// Make a writer for the output stream to
                                                                            // the client
        BufferedReader reader = new BufferedReader(new FileReader(index));// grab a file and put it into the buffer
        // print HTTP headers
        printWriter.println("HTTP/1.1 200 OK");
        printWriter.println("Content-Type: text/html");
        printWriter.println("Content-Length: " + index.length());
        printWriter.println("\r\n");
        String line = reader.readLine();// line to go line by line from file
        while (line != null)// repeat till the file is read
        {
            printWriter.println(line);// print current line

            line = reader.readLine();// read next line
        }
        reader.close();// close the reader
        printWriter.close();
    }
person Alex Rudenko    schedule 16.04.2020
comment
Спасибо, мне не пришлось использовать index.length(), но я уверен, что это пригодится, когда дело доходит до больших файлов. Моя самая большая проблема заключалась в том, что я пытался добавить HTTP/.... в \r\n внутри самого файла. Выполнение этого в коде, а затем чтение только http в файле сделало эту работу. Спасибо еще раз! - person Msnoyce; 17.04.2020
comment
Протестировал сценарий, когда HTTP-заголовки появляются внутри файла, а между заголовками и телом есть пустая строка - тоже работало нормально :) - person Alex Rudenko; 17.04.2020
comment
@Msnoyce, если вы считаете, что мой ответ был полезен, отметьте его как принятый :) Спасибо! - person Alex Rudenko; 17.04.2020
comment
Извините. Новое в публикации в stackoverflow. Я отметил это сейчас. Кроме того, совет о добавлении длины файла пригодится в более поздней части этого проекта, так что еще раз спасибо за это! - person Msnoyce; 19.04.2020