При попытке скачать файл с собственного реализованного http-сервера на Jave бразер дико лагает и скорость низкая

Рейтинг: 1Ответов: 1Опубликовано: 15.04.2023

Собственно вот такой вот код:

if(Files.exists(Path.of(HttpServer.directory+path)) && ! Files.isDirectory(Path.of(HttpServer.directory+path))) {
    // System.out.println("File exists: "+HttpServer.directory+path);
    File f = new File(HttpServer.directory+path);
    String header = "HTTP/1.1 200 OK\nContent-type: file/file\nContent-Length: " + f.length() + "\nConnection: close\n\n";
    InputStream fileContent = new FileInputStream(f);
    out.write(header.getBytes("UTF-8"));
    while (fileContent.available() > 0)
        out.write(fileContent.read());
    out.flush();
}

HttpServer.directory - содержит в себе путь до директории, в которой будет происходить хостинг файлов на http-сервере, она указывается в аргументах запуска, в моем случае это C:/PFB/Server, а path - содержит в себе URI из http-запроса GET.

HttpServer запущен на 8080 порте.
Итак, у меня на ПК содержится файл по пути C:/PFB/Server/asd.exe весом 578 мб, а так же по пути C:/PFB/Server у меня находится еще парочка мелких файлов.

Я захожу в браузер, пытаюсь сначала скачать эту парочку файлов, всё успешно, но когда я ввожу http://localhost:8080/asd.exe, то есть хочу скачать большой файл, у меня браузер начинает дико виснуть, скорость загрузки 20 кб/с, при попытке что-то делать браузер не отвечает.

Может, файл нельзя закидывать целиком в HTTP-ответ? Может, нужно создать несколько TCP соединений?

Нигде данной информации я не нашел.
В чём заключается проблема, и есть ли по этому поводу статьи в интернете?

Ответы

▲ 0

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

if (Files.exists(Path.of(HttpServer.directory+path)) && ! Files.isDirectory(Path.of(HttpServer.directory+path))) {
    File f = new File(HttpServer.directory+path);
    long contentLength = f.length();
    String contentType = Files.probeContentType(f.toPath());
    String header = "HTTP/1.1 200 OK\nContent-type: " + contentType + "\nContent-Length: " + contentLength + "\nConnection: close\n\n";
    out.write(header.getBytes("UTF-8"));
    try (InputStream fileContent = new BufferedInputStream(new FileInputStream(f))) {
        byte[] buffer = new byte[4096];
        int bytesRead;
        while ((bytesRead = fileContent.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
    }
    out.flush();} 

Размер буфера выбираем в зависимости от настроенного приема на HTTP сервере.