Rocket框架雖然可以提供靜態檔案,但有時候我們的資料來源並不是檔案,而可能是從資料庫撈出來的資料,或者是由程式動態產生出來的資料。雖然Rocket框架可以直接使用Vec<u8>
來作為回應的型別,但使用起來並不是很方便,因為在回應二進制資料時,除非是讓特定程式存取的API,不然我們幾乎是一定會需要替回應的資料設定內容類型(Content-Type)的,否則網頁瀏覽器就不會知道伺服器回應的資料要如何開啟,而直接跳出下載視窗。
Raw Response for Rocket Framework
「Raw Response for Rocket Framework」是筆者開發的套件,可以使Rocket框架直接回應一個Vec<u8>
實體、一個Reader或是一個檔案,並且快速地替其加入Content-Type
標頭。
Crates.io
Cargo.toml
使用方法
rocket_raw_response
這個crate提供的RawResponse
結構體可以當作要回應的資料型別。RawResponse
結構體提供了from_static
關聯函數和from_vec
關聯函數,可以從參數中傳入要拿來回應的&'static [u8]
參考或Vec<u8>
實體、檔案類型和開啟時預設的檔案名稱(如果不設定檔案名稱的話,網頁瀏覽器會用網址路徑的檔案名稱來當作檔案名稱)。它也提供了from_reader
關聯函數,可以從參數中傳入任意有實作Read
特性的實體、檔案類型和開啟時預設的檔案名稱。
如果資料來源為檔案的話,那就更方便了,可以直接使用RawResponse
結構體提供的from_file
關聯函數,可以從參數中傳入檔案路徑、檔案類型和開啟時預設的檔案名稱。如果不提供檔案類型的話,預設會由檔案路徑中的副檔名來判斷;如果不提供檔案名稱的話,預設會由檔案路徑中的檔案名稱來判斷;如果想要直接使用網址路徑的檔案名稱作為預設的檔案名稱的話,那就把檔案名稱設定為空字串。
舉個例子,假設工作目錄中有image.jpg
這張JPEG圖檔。若想要讓Rocket框架提供這個圖檔,並且讓網頁瀏覽器直接瀏覽這個圖檔,而不是將其下載到檔案系統的話,程式可以這樣寫:
#[macro_use]
extern crate rocket;
use std::io::ErrorKind;
use std::path::Path;
use rocket::http::Status;
use rocket_raw_response::RawResponse;
#[get("/")]
async fn view() -> Result<RawResponse, Status> {
let path = Path::join(Path::new("examples"), Path::join(Path::new("images"), "image.jpg"));
RawResponse::from_file(path, None::<String>, None).await.map_err(|err| {
if err.kind() == ErrorKind::NotFound {
Status::NotFound
} else {
Status::InternalServerError
}
})
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![view])
}