本博客是在楊旭老師的 rust web 全棧教程項目基礎(chǔ)上進行修改,支持了圖片資源返回,楊旭老師的rust web鏈接如下:
https://www.bilibili.com/video/BV1RP4y1G7KFp=1&vd_source=8595fbbf160cc11a0cc07cadacf22951
本人默認(rèn)讀者已經(jīng)學(xué)習(xí)了相關(guān)基礎(chǔ)教程和楊旭老師的相關(guān)課程,直接開始針對項目里面對應(yīng)文件進行修改說明。
一、新增加載圖片資源方法
在原先項目加載文件方法同一層,新增支持加載圖片資源如下。
pub trait Handler{
fn handle(res:&HttpRequest) ->HttpResponse;
fn load_file(file_name:&str) ->Option<Vec<u8>>{
println!("load_file file_name={}",file_name);
let default_path = format!("{}/public",env!("CARGO_MANIFEST_DIR"));
println!("load_file default_path={}",default_path);
let public_path = env::var("PUBLIC_PATH").unwrap_or(default_path);
let full_path = format!("{}/{}",public_path,file_name);
println!("load_file full_path={}",full_path);
let contents = fs::read(full_path);
contents.ok()
}
fn load_image(image_name:&str) ->Option<Vec<u8>>{
let default_path = format!("{}/public",env!("CARGO_MANIFEST_DIR"));
let public_path = env::var("PUBLIC_PATH").unwrap_or(default_path);
let full_path = format!("{}/{}/{}",public_path,"image",image_name);
println!("load_image full_path={}",full_path);
let contents: Result<Vec<u8>, std::io::Error> = fs::read(full_path);
contents.ok()
}
}
load_image 方法就是本博客新增方法,根據(jù)入?yún)D片名稱,去指定public目錄下image文件夾下讀取圖片文件,返回Vec<u8> 字節(jié)流。
我們在舊的新增了圖片處理分支如下
impl Handler for StaticPageHandler{
fn handle(req:&HttpRequest) ->HttpResponse{
let http::httprequest::Resource::Path(s) =&req.resourece;
let route:Vec<&str> = s.split("/").collect();
println!("route={}",route[1]);
if route[1]=="image" {
match Self::load_image(route[2]){
Some(content) => {
let mut map:HashMap<&str,&str> = HashMap::new();
map.insert("Content-Type","image/webp");
println!("讀取到文件長度{}",content.len());
return HttpResponse::new("200",Some(map),Some(content));
},
None => {
return HttpResponse::new("404",None,Self::load_file("404.html"))
}
}
}match route[1] {
"" =>HttpResponse::new("200",None,Self::load_file("index.html")),
"health" =>HttpResponse::new("200",None,Self::load_file("health.html")),
path => match Self::load_file(path) {
Some(contents) =>{
let mut map:HashMap<&str,&str> = HashMap::new();
if path.ends_with(".css") {
map.insert("Content-Type","text/css");
}else if path.ends_with(".js") {
map.insert("Content-Type","text/javascript");
}else {
map.insert("Content-Type","text/html");
}
HttpResponse::new("200",Some(map),Some(contents))
},
None => HttpResponse::new("404",None,Self::load_file("404.html"))
}
}
}
}
特別說明點根據(jù)加載圖片類型不同,map.insert("Content-Type","image/webp");
這里的Content-Type也要對應(yīng)修改,我這里返回的文件是webp格式。
二、修改HttpResponse 結(jié)構(gòu)體body數(shù)據(jù)類型
舊項目中由于返回的都是文本內(nèi)容,body數(shù)據(jù)類型定義成字符串切片,由于這次改動讀取圖片是字節(jié)流,所以這里的body也需要變更成Option<Vec<u8>>類型
#[derive(Debug,PartialEq,Clone)]
pub struct HttpResponse<'a>{
version:&'a str,
status_code:&'a str,
status_text:&'a str,
header:Option<HashMap<&'a str,&'a str>>,
body:Option<Vec<u8>>,
}
三、修改HttpResponse 響應(yīng)方法
上面已經(jīng)提到了,舊項目返回的是文本內(nèi)容,故在發(fā)送HttpResponse數(shù)據(jù)是,直接將數(shù)據(jù)轉(zhuǎn)化成字符串發(fā)送。這里我們?yōu)榱思嫒輬D片資源的響應(yīng),所以body為Vec<u8>類型時就不適用先前的方法。我們對除了body字段,其他字段依然按照舊的邏輯轉(zhuǎn)化成字符串。
impl <'a> From<HttpResponse<'a>> for String{
fn from(res:HttpResponse) -> String{
let res1 = res.clone();
format!("{} {} {}\r\n{}Content-Length:{}\r\n\r\n",
&res1.version(),
&res1.status_code(),
&res1.status_text(),
&res1.header(),
&res.body.unwrap().len(),
)
}
}
?相比較舊的方法,我們?nèi)サ袅薭ody參數(shù)。
四、返回body數(shù)據(jù)
上面講過了,我們在響應(yīng)轉(zhuǎn)String時,將body數(shù)據(jù)拆分出來了,那么通過什么方法返回body數(shù)據(jù)。
pub fn send_response(&self, write_stream:&mut impl Write) -> Result<(),std::io::Error>{
let res = self.clone();
let response_string: String = String::from(res); // from trait
write_stream.write(response_string.as_bytes()).unwrap();
write_stream.write(&self.body()).unwrap();
write_stream.flush().unwrap();
Ok(())
}
?我們就是通過write_stream.write(&self.body()).unwrap();將body數(shù)據(jù)再獨立發(fā)送一下。文章來源:http://www.zghlxwxcb.cn/news/detail-498021.html
整理上來講改動很小,就是將body數(shù)據(jù)類型從&str,改成了Vec<u8>,在發(fā)送響應(yīng)時將body拆分出來發(fā)送。文章來源地址http://www.zghlxwxcb.cn/news/detail-498021.html
到了這里,關(guān)于Rust 自建HTTP Server支持圖片響應(yīng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!