Skip to content

服務靜態內容

無論您是正在建立網站還是 HTTP 端點,您的應用程式很可能需要服務檔案,例如 樣式表、腳本或圖片。 雖然 Ktor 確實能夠載入檔案內容並在回應中傳送給客戶端,但 Ktor 透過提供額外的函式來簡化此過程,以服務靜態內容。

使用 Ktor,您可以從資料夾ZIP 檔案 以及嵌入式應用程式資源服務內容。

資料夾

若要從本機檔案系統服務靜態檔案,請使用 staticFiles() 函式。在此情況下,相對路徑會使用目前工作目錄解析。

kotlin
routing {
    staticFiles("/resources", File("files"))
}

在上述範例中,任何來自 /resources 的請求都會映射到目前工作目錄中名為 files 的實體資料夾。 只要 URL 路徑和實體檔案名稱匹配,Ktor 就會遞迴地服務 files 中的任何檔案。

有關完整範例, 請參閱 static-files

ZIP 檔案

若要從 ZIP 檔案服務靜態內容,Ktor 提供了 staticZip() 函式。 這允許您將請求直接映射到 ZIP 壓縮檔的內容,如下列範例所示:

kotlin
routing {
    staticZip("/", "", Paths.get("files/text-files.zip"))
}

在此範例中,任何來自根 URL / 的請求都會直接映射到 text-files.zip ZIP 檔案的內容。

自動重新載入支援

staticZip() 函式也支援自動重新載入。如果在 ZIP 檔案的父目錄中偵測到任何變更,ZIP 檔案系統會在下次請求時重新載入。這確保了服務的內容保持 最新,而無需伺服器重新啟動。

有關完整範例, 請參閱 static-zip

資源

若要從類路徑服務內容,請使用 staticResources() 函式。

kotlin
routing {
    staticResources("/resources", "static")
}

這會將任何來自 /resources 的請求映射到應用程式資源中的 static 套件。 在此情況下,只要 URL 路徑和資源路徑匹配,Ktor 就會遞迴地服務 static 套件中的任何檔案。

有關完整範例, 請參閱 static-resources

額外配置

Ktor 為靜態檔案和資源提供了更多配置。

索引檔案

如果存在名為 index.html 的檔案,當請求目錄時,Ktor 預設會服務該檔案。您可以使用 index 參數設定自訂索引檔案:

kotlin
staticResources("/custom", "static", index = "custom_index.html")

在此情況下,當請求 /custom 時,Ktor 會服務 /custom_index.html

預壓縮檔案

Ktor 提供了服務預壓縮檔案並避免使用動態壓縮的能力。 要使用此功能,請在區塊語句中定義 preCompressed() 函式:

kotlin
staticFiles("/", File("files")) {
    preCompressed(CompressedFileType.BROTLI, CompressedFileType.GZIP)
}

在此範例中,對於對 /js/script.js 的請求,Ktor 可以服務 /js/script.js.br/js/script.js.gz

HEAD 請求

enableAutoHeadResponse() 函式允許您自動回應靜態路由中每個定義了 GET 的路徑的 HEAD 請求。

kotlin
staticResources("/", "static"){
    enableAutoHeadResponse()
}

預設檔案回應

default() 函式提供了為靜態路由中任何沒有對應檔案的請求回覆檔案的能力。

kotlin
staticFiles("/", File("files")) {
    default("index.html")
}

在此範例中,當客戶端請求不存在的資源時,會將 index.html 檔案作為回應服務。

內容類型

預設情況下,Ktor 會嘗試從檔案副檔名猜測 Content-Type 標頭的值。您可以使用 contentType() 函式來明確設定 Content-Type 標頭。

kotlin
staticFiles("/files", File("textFiles")) {
    contentType { file ->
        when (file.name) {
            "html-file.txt" -> ContentType.Text.Html
            else -> null
        }
    }
}

在此範例中,檔案 html-file.txt 的回應將具有 Content-Type: text/html 標頭,而對於其他所有檔案,將應用預設行為。

快取

cacheControl() 函式允許您為 HTTP 快取配置 Cache-Control 標頭。

kotlin
    install(ConditionalHeaders)
    routing {
        staticFiles("/files", File("textFiles")) {
            cacheControl { file ->
                when (file.name) {
                    "file.txt" -> listOf(Immutable, CacheControl.MaxAge(10000))
                    else -> emptyList()
                }
            }
        }
    }
}
object Immutable : CacheControl(null) {
    override fun toString(): String = "immutable"
}

ConditionalHeaders 外掛安裝後,Ktor 可以使用 ETagLastModified 標頭服務靜態資源,並處理條件式標頭,以避免在內容自上次請求後未更改時傳送內容主體:

kotlin
staticFiles("/filesWithEtagAndLastModified", File("files")) {
    etag { resource -> EntityTagVersion("etag") }
    lastModified { resource -> GMTDate() }
}

在此範例中,etaglastModified 值根據每個資源動態計算,並應用於回應。

為了簡化 ETag 的生成,您也可以使用預定義的提供者:

kotlin
staticFiles("/filesWithStrongGeneratedEtag", File("files")) {
    etag(ETagProvider.StrongSha256)
}

在此範例中,使用資源內容的 SHA‑256 雜湊生成一個強 ETag。 如果發生 I/O 錯誤,則不會生成 ETag

有關 Ktor 中快取的更多資訊,請參閱快取標頭

排除的檔案

exclude() 函式允許您排除不被服務的檔案。當客戶端請求排除的檔案時, 伺服器將以 403 Forbidden 狀態碼回應。

kotlin
staticFiles("/files", File("textFiles")) {
    exclude { file -> file.path.contains("excluded") }
}

檔案副檔名回溯

當找不到請求的檔案時,Ktor 可以將給定的副檔名新增到檔案名稱並搜尋它。

kotlin
staticResources("/", "static"){
    extensions("html", "htm")
}

在此範例中,當請求 /index 時,Ktor 將搜尋 /index.html 並服務找到的內容。

自訂回退

為了在請求的靜態資源未找到時配置自訂回退行為,請使用 fallback() 函式。 透過 fallback(),您可以檢查請求的路徑並決定如何回應。例如,您可能重定向到 另一個資源、返回特定的 HTTP 狀態碼或服務一個替代檔案。

您可以將 fallback() 新增到 staticFiles()staticResources()staticZip()staticFileSystem() 中。回呼提供 了請求路徑和目前的 ApplicationCall

以下範例展示了如何重定向某些副檔名、返回自訂狀態或回退到 index.html

kotlin
staticFiles("/files", File("textFiles")) {
    fallback { requestedPath, call ->
        when {
            requestedPath.endsWith(".php") -> call.respondRedirect("/static/index.html") // absolute path
            requestedPath.endsWith(".kt") -> call.respondRedirect("Default.kt") // relative path
            requestedPath.endsWith(".xml") -> call.respond(HttpStatusCode.Gone)
            else -> call.respondFile(File("files/index.html"))
        }
    }
}

自訂修改

modify() 函式允許您對結果回應應用自訂修改。

kotlin
staticFiles("/", File("files")) {
    modify { file, call ->
        call.response.headers.append(HttpHeaders.ETag, file.name.toString())
    }
}

處理錯誤

如果找不到請求的內容,Ktor 將自動以 404 Not Found HTTP 狀態碼回應。

要了解如何配置錯誤處理,請參閱 Status Pages