在先前的文章中,我們介紹了能讓Rocket框架直接回應MongoDB檔案中心裡的檔案的方法。如果想要讓網頁瀏覽器在收到伺服器傳來的檔案資料時,將其下載成檔案的話,可以參考這篇文章。
File Center Download Response on MongoDB for Rocket Framework
「File Center Download Response on MongoDB for Rocket Framework」是筆者開發的套件,可以讓「Mongo File Center」套件融入Rocket框架中,能直接從檔案中心回應檔案資料,並且讓網頁瀏覽器直接將其下載成檔案。
Crates.io
https://crates.io/crates/rocket-mongo-file-center-download-response
Cargo.toml
rocket-mongo-file-center-download-response = "*"
使用方法
先將mongo_file_center
這個crate下的FileCenter
結構實體註冊至Rocket框架的應用程式狀態中。在路由處理程序中,可以利用State<FileCenter>
的inner
方法取得FileCenter
結構實體的參考。
rocket_mongo_file_center_download_response
這個crate提供了FileCenterDownloadResponse
結構體。
FileCenterDownloadResponse
結構體有三個關聯函數可以用來產生FileCenterDownloadResponse
結構體的實體。
首先介紹最常用的from_id_token
函數。呼叫from_id_token
函數時,要從參數傳入FileCenter
結構實體的參考、檔案中心加密過的Object ID(ID token)和檔案名稱(如果不設定則使用檔案中心儲存的檔案名稱)。
以下是一個完整的例子:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
extern crate rocket_mongo_file_center_download_response;
extern crate validators;
use std::path::Path;
use rocket_mongo_file_center_download_response::FileCenterDownloadResponse;
use rocket_mongo_file_center_download_response::mongo_file_center::{FileCenter, FileCenterError, mime};
use rocket::request::State;
use validators::short_crypt_url_component::ShortCryptUrlComponent;
const HOST: &str = "localhost";
const PORT: u16 = 27017;
#[get("/<id_token>")]
fn download(file_center: State<FileCenter>, id_token: ShortCryptUrlComponent) -> Result<Option<FileCenterDownloadResponse>, FileCenterError> {
FileCenterDownloadResponse::from_id_token(file_center.inner(), id_token.into_string(), None::<String>)
}
fn main() {
let database = "test_rocket_mongo_file_center_download_response";
let file_center = FileCenter::new(HOST, PORT, database).unwrap();
let path = Path::new("image.jpg");
let file = file_center.put_file_by_path(path, None::<String>, Some(mime::IMAGE_JPEG)).unwrap();
let id_token = file_center.encrypt_id(file.get_object_id());
println!("The ID token is: {}", id_token);
println!();
rocket::ignite().manage(file_center).mount("/", routes![download]).launch();
}
程式一開始,會將工作目錄下的image.jpg
這張JPEG圖檔儲存到檔案中心中,然後在螢幕上顯示出這筆加密過的Object ID(也就是「ID token」)。接著將檔案中心註冊給Rocket,並啟動Rocket。在download
這個路由處理程序中,會讀取網址路徑中帶的ID token。(ShortCryptUrlComponent
結構體來自於validators
這個crate,有關於validators
的介紹可以參考這篇文章。)from_id_token
會根據這個ID token來查詢檔案中心裡對應的檔案,並回傳Result<Option<FileCenterDownloadResponse>, FileCenterError>
,注意因為這邊的FileCenterError
並沒有實作rocket::response::Responder
特性,所以如果直接拿來回傳的話,等同於發生500
錯誤。
如果是要用from_object_id
關聯函數來建立FileCenterDownloadResponse
結構實體,把以上的download
路由處理程序用from_object_id
關聯函數改寫的話就會變成以下這樣:
#[get("/<id_token>")]
fn download(file_center: State<FileCenter>, id_token: ShortCryptUrlComponent) -> Result<Option<FileCenterDownloadResponse>, FileCenterError> {
let id_token = id_token.into_string();
let object_id = file_center.decrypt_id_token(&id_token)?;
FileCenterDownloadResponse::from_object_id(file_center.inner(), &object_id, None::<String>)
}
如果已經從檔案中心拿到FileItem
了,可以使用FileCenterDownloadResponse
結構體的from_file_item
關聯函數來產生FileCenterDownloadResponse
結構實體,如下:
#[get("/<id_token>")]
fn download(file_center: State<FileCenter>, id_token: ShortCryptUrlComponent) -> Result<Option<FileCenterDownloadResponse>, FileCenterError> {
let id_token = id_token.into_string();
let object_id = file_center.decrypt_id_token(&id_token)?;
let file_item = file_center.get_file_item_by_id(&object_id)?;
match file_item {
Some(file_item) => {
Ok(Some(FileCenterDownloadResponse::from_file_item(file_item, None::<String>)))
}
None => {
Ok(None)
}
}
}