Правильный способ отправить файл через сокет в Java после запроса GET из браузера - PullRequest
0 голосов
/ 07 ноября 2019

Я использую браузер для отправки запроса на получение сервера, просто набрав адрес 127.0.0.1:1501/filename.png. Цель состоит в том, чтобы загрузить файл с сервера. Сервер успешно принимает запрос и загружает выбранный файл, он также входит в цикл while и несколько раз выполняет метод печати, означая, что что-то отправляет, но при проверке Google Chrome на вкладке «сеть» я получаю только filename.pngне удалось понять, почему этот код не работаетprint - это метод, который просто вызывает метод System.out.println ()

public class MainClassServer {
    public static void main(String[] args){
        // TODO Auto-generated method stub
        ServerSocket server = null;
        try {
            server = new ServerSocket();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        try {
            server.bind(new InetSocketAddress("127.0.0.1", 1501));
        } catch (UnknownHostException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }


        while(true) {
            String message;
            Socket client = null;
            print("Waiting for client...");
            try{
                client = server.accept();
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
            BufferedReader reader = null;
            DataOutputStream writer = null;

            try {
                reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
                writer = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                message = reader.readLine();

                if(message!=null) {
                    //I get the correct filename with string manipulation
                    // I correctly access the file in fact it exist
                    File file = new File(path);

                    if(file.exists()) {
                        byte[] bytes = new byte[1024];
                        InputStream in = new FileInputStream(path);
                        int count;
                        while ((count = in.read(bytes)) > 0) {
                            //the program print some bytes so it writes something to someone
                            print("Sending " + count + " bytes");
                            writer.write(bytes, 0, count);
                        }
                        writer.flush();
                    }else {
                        print("File does not exsist.");
                    }


                    writer.close();
                    reader.close();
                    server.close();
                    break;  
                }

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }


}

Ответы [ 2 ]

2 голосов
/ 07 ноября 2019

Браузер всегда ожидает HTTP-ответа в ответ на запрос. Если у вас есть клиент, который является простым сокет-клиентом, вы получите файл при записи в DataOutputStream для HTTP, по крайней мере, вам нужен минимальный формат ответа HTTP. Если вы добавите эти 2 заголовка в свой ответ, вы можете получить ожидаемое поведение.

if(file.exists()) {
    byte[] bytes = new byte[1024];
    InputStream in = new FileInputStream(path);
    int count;
    // Setting HTTP response headers
    writer.writeBytes("HTTP/1.0 200 OK\r\n");
    writer.writeBytes("Content-Type: image/jpeg\r\n");
    writer.writeBytes("\r\n");
    while ((count = in.read(bytes)) > 0) {
        //the program print some bytes so it writes something to someone
        print("Sending " + count + " bytes");
        writer.write(bytes, 0, count);
    }
    writer.flush();
}else {
    print("File does not exsist.");
}
2 голосов
/ 07 ноября 2019

Вы НЕ следуете протоколу HTTP 1.x вообще, даже не близко:

  • вы НЕ читаете и не анализируете HTTP-запрос браузера. Вы читаете только 1-ю строку запроса, игнорируя остальную часть запроса (может быть и обычно больше 1 строки). И вы даже не анализируете эту 1-ю строку - в ней больше данных, чем просто путь к файлу. Он содержит имя метода запроса (т. Е. GET), затем путь к файлу и номер версии HTTP.

  • вы НЕ отправляете обратно правильно отформатированный ответ HTTP. Вы просто отправляете необработанные байты файла как есть, не сообщая клиенту, был ли запрос успешным или нет, или не описывая, какие данные файла вы отправляете. Вы должны отправить обратно строку состояния HTTP, содержащую номер версии HTTP, затем код ошибки успеха / сбоя и текст статуса, понятный человеку. Затем отправьте HTTP-заголовки, описывающие тип файла, длину, формат передачи и т. Д. Затем, наконец, отправьте байты файла.

По сути, вы реализовали HTTP 0,9 сервер (который использует однострочные запросы, которые вы по-прежнему неправильно анализируете, и никаких дополнительных подробностей ответа, кроме необработанных байтов файла). Этот тип сервера не будет работать для запросов HTTP 1.0+, которые используются всеми современными веб-браузерами. HTTP 1.1 сейчас является стандартом де-фактора, который используют большинство современных систем (хотя многие начинают переходить на HTTP / 2 ).

Вы действительно должны использовать правильный HTTPсервер, а не обычный ванильный TCP-сервер. HTTP является сложным и нетривиальным для реализации с нуля. Вместо этого вы должны использовать уже существующую реализацию. Например, Java имеет встроенный класс HttpServer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...