從零手寫實現 nginx-06-資料夾內容的自動索引展示

老马啸西风發表於2024-06-05

前言

大家好,我是老馬。很高興遇到你。

我們希望實現最簡單的 http 服務資訊,可以處理靜態檔案。

如果你想知道 servlet 如何處理的,可以參考我的另一個專案:

手寫從零實現簡易版 tomcat minicat

手寫 nginx 系列

如果你對 nginx 原理感興趣,可以閱讀:

從零手寫實現 nginx-01-為什麼不能有 java 版本的 nginx?

從零手寫實現 nginx-02-nginx 的核心能力

從零手寫實現 nginx-03-nginx 基於 Netty 實現

從零手寫實現 nginx-04-基於 netty http 出入參最佳化處理

從零手寫實現 nginx-05-MIME型別(Multipurpose Internet Mail Extensions,多用途網際網路郵件擴充套件型別)

從零手寫實現 nginx-06-資料夾自動索引

從零手寫實現 nginx-07-大檔案下載

從零手寫實現 nginx-08-範圍查詢

從零手寫實現 nginx-09-檔案壓縮

從零手寫實現 nginx-10-sendfile 零複製

從零手寫實現 nginx-11-file+range 合併

從零手寫實現 nginx-12-keep-alive 連線複用

從零手寫實現 nginx-13-nginx.conf 配置檔案介紹

從零手寫實現 nginx-14-nginx.conf 和 hocon 格式有關係嗎?

從零手寫實現 nginx-15-nginx.conf 如何透過 java 解析處理?

從零手寫實現 nginx-16-nginx 支援配置多個 server

目標

這一節我們想實現如果訪問的是資料夾,我們就把資料夾內容全部列出來。

然後使用者可以自己點選跳轉,實現資料夾的自動索引。

思路

直接判斷是否為資料夾,如果是則列出所有的檔案資訊。

然後構建一個 html 返回即可。

核心實現

資料夾響應

    /**
     * 構建資料夾結果
     * @param targetFile 目標檔案
     * @param request 請求
     * @param nginxConfig 配置
     * @return 結果
     * @since 0.5.0
     * @author 老馬嘯西風
     */
    protected FullHttpResponse buildDirResp(File targetFile, final FullHttpRequest request, final NginxConfig nginxConfig) {
        try {
            String html = generateFileListHTML(targetFile, request, nginxConfig);

            byte[] fileContent = html.getBytes(nginxConfig.getCharset());
            FullHttpResponse response = buildCommentResp(fileContent, HttpResponseStatus.OK, request, nginxConfig);
            setContentType(response, "text/html;");
            return response;
        } catch (Exception e) {
            throw new Nginx4jException(e);
        }
    }

資料夾對應的內容

protected String generateFileListHTML(File directory, final FullHttpRequest request, final NginxConfig nginxConfig) {
        // 確保傳入的是一個目錄
        if (!directory.isDirectory()) {
            return "Error: The specified path is not a directory.";
        }

        StringBuilder htmlBuilder = new StringBuilder();
        htmlBuilder.append("<html><head><title>File List</title></head><body>");
        htmlBuilder.append("<h1>File List</h1>");
        htmlBuilder.append("<ul>");

        File[] fileList = directory.listFiles();

        for (File file : fileList) {
            String fileName = file.getName();
            String fileLink = getFileLink(file, request, nginxConfig);
            htmlBuilder.append("<li><a href=\"").append(fileLink).append("\">").append(fileName).append("</a></li>");
        }

        htmlBuilder.append("</ul></body></html>");
        return htmlBuilder.toString();
}

其中連結的構建也很簡單:

protected String getFileLink(File file, final FullHttpRequest request, final NginxConfig nginxConfig) {
    String fileName = file.getName();
    return FileUtil.buildFullPath(request.uri(), fileName);
}

小結

本節我們實現了一個資料夾的自動索引支援,整體而言非常簡單。

當然,也可以新增樣式,或者是【..】之類的上級跳轉,讓使用者體驗更佳。我們暫時不做處理。

甚至做的更好一些,可以加上常見檔案型別的 logo。

下一節,我們一起來看一下大檔案分段請求的處理。

我是老馬,期待與你的下次重逢。

開源地址

為了便於大家學習,已經將 nginx 開源

https://github.com/houbb/nginx4j

相關文章