rust yew 0.20 文件上传功能

536 阅读1分钟

在网站找了很多地方,都没找到详细的文件上传的代码。这里分享一下,yew框架如何进行文件上传,希望能够帮助到大家。

upload 方法

首页,我们写一个上传文件的方法

use gloo_net::http::{Method, Request};
use serde::de::DeserializeOwned;
use serde::Serialize;

use gloo_storage::{LocalStorage, Storage};
use std::format;
use web_sys::FormData;

pub async fn upload<'a, R>(url: &'a str, params: &FormData) -> Result<R, String>
where
    R: Serialize + DeserializeOwned + Clone,
{
    let res = Request::new(format!("{}{}", "http://localhost:3060", url).as_str())
        // .header("Content-Type", "multipart/form-data")  // 可能不需要这个content type
        .body(params)
        .method(Method::POST)
        .send()
        .await;
    match res {
        Ok(r) => match r.json::<R>().await {
            Ok(r0) => Ok(r0),
            Err(e) => Err(e.to_string()),
        },
        Err(e) => Err(e.to_string()),
    }
}

我们web端上传文件,以FormData的格式上传,所以,params的类型为&FormData。然后,body()里面直接传入params参数就可以了。

上传组件

然后,我们写一个上传文件的组件:upload_file.rs

use js_sys;
use serde_json;
use stylist::css;
use web_sys::{Event, FormData, HtmlInputElement};
use yew::prelude::*;

use crate::constants::upload;  // 引入上面的upload方法,根据你的位置修改引入。

#[function_component]
pub fn UploadFile() -> Html {
    let onchange = {
        Callback::from(move |e: Event| {
            let input: HtmlInputElement = e.target_unchecked_into();
            let form_data = FormData::new().unwrap();
            if let Some(files) = input.files() {
                // 将选择的文件数据,转换成 web_sys 的 Blob 格式。
                let files = js_sys::try_iter(&files)
                    .unwrap()
                    .unwrap()
                    .map(|v| web_sys::Blob::from(v.unwrap()));
                    
                // 因只上传单个文件,files的长度为1
                for file in files {
                    form_data.append_with_blob("file", &file).unwrap();
                }
            }
            wasm_bindgen_futures::spawn_local(async move {
                // 调用上面的 upload 方法,进行文件上传。
                let res: Result<serde_json::Value, String> =
                    upload("/upload/image", &form_data).await;
                log::info!("上传成功 {:?}", res);
            })
        })
    };

    html! {
        <input type="file" {onchange} />
    }
}

组件如下图,当我们点击选择文件的时候,它就上传成功了 image.png