161 lines
5.3 KiB
Rust
161 lines
5.3 KiB
Rust
use crate::fat_error::{FatError, FatResult};
|
|
use crate::webserver::read_up_to_bytes_from_request;
|
|
use crate::BOARD_ACCESS;
|
|
use alloc::borrow::ToOwned;
|
|
use alloc::format;
|
|
use alloc::string::String;
|
|
use edge_http::io::server::Connection;
|
|
use edge_http::Method;
|
|
use edge_nal::io::{Read, Write};
|
|
use log::info;
|
|
|
|
pub(crate) async fn list_files<T, const N: usize>(
|
|
_request: &mut Connection<'_, T, N>,
|
|
) -> FatResult<Option<String>> {
|
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
|
let result = board.board_hal.get_esp().list_files().await?;
|
|
let file_list_json = serde_json::to_string(&result)?;
|
|
Ok(Some(file_list_json))
|
|
}
|
|
pub(crate) async fn file_operations<T, const N: usize>(
|
|
conn: &mut Connection<'_, T, { N }>,
|
|
method: Method,
|
|
path: &&str,
|
|
prefix: &&str,
|
|
) -> Result<Option<u32>, FatError>
|
|
where
|
|
T: Read + Write,
|
|
{
|
|
let filename = &path[prefix.len()..];
|
|
info!("file request for {filename} with method {method}");
|
|
Ok(match method {
|
|
Method::Delete => {
|
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
|
board
|
|
.board_hal
|
|
.get_esp()
|
|
.delete_file(filename.to_owned())
|
|
.await?;
|
|
conn.initiate_response(
|
|
200,
|
|
Some("OK"),
|
|
&[
|
|
("Access-Control-Allow-Origin", "*"),
|
|
("Access-Control-Allow-Headers", "*"),
|
|
("Access-Control-Allow-Methods", "*"),
|
|
],
|
|
)
|
|
.await?;
|
|
Some(200)
|
|
}
|
|
Method::Get => {
|
|
let disposition = format!("attachment; filename=\"{filename}\"");
|
|
let size = {
|
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
|
board
|
|
.board_hal
|
|
.get_esp()
|
|
.get_size(filename.to_owned())
|
|
.await?
|
|
};
|
|
|
|
conn.initiate_response(
|
|
200,
|
|
Some("OK"),
|
|
&[
|
|
("Content-Type", "application/octet-stream"),
|
|
("Content-Disposition", disposition.as_str()),
|
|
("Content-Length", &format!("{size}")),
|
|
("Access-Control-Allow-Origin", "*"),
|
|
("Access-Control-Allow-Headers", "*"),
|
|
("Access-Control-Allow-Methods", "*"),
|
|
],
|
|
)
|
|
.await?;
|
|
|
|
let mut chunk = 0;
|
|
loop {
|
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
|
board.board_hal.progress(chunk).await;
|
|
let read_chunk = board
|
|
.board_hal
|
|
.get_esp()
|
|
.get_file(filename.to_owned(), chunk)
|
|
.await?;
|
|
let length = read_chunk.1;
|
|
if length == 0 {
|
|
info!("file request for {filename} finished");
|
|
break;
|
|
}
|
|
let data = &read_chunk.0[0..length];
|
|
conn.write_all(data).await?;
|
|
if length < read_chunk.0.len() {
|
|
info!("file request for {filename} finished");
|
|
break;
|
|
}
|
|
chunk += 1;
|
|
}
|
|
BOARD_ACCESS
|
|
.get()
|
|
.await
|
|
.lock()
|
|
.await
|
|
.board_hal
|
|
.clear_progress()
|
|
.await;
|
|
Some(200)
|
|
}
|
|
Method::Post => {
|
|
{
|
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
|
//ensure the file is deleted first; otherwise we would need to truncate the file which will not work with streaming
|
|
let _ = board
|
|
.board_hal
|
|
.get_esp()
|
|
.delete_file(filename.to_owned())
|
|
.await;
|
|
}
|
|
|
|
let mut offset = 0_usize;
|
|
let mut chunk = 0;
|
|
loop {
|
|
let buf = read_up_to_bytes_from_request(conn, Some(4096)).await?;
|
|
if buf.is_empty() {
|
|
info!("file request for {filename} finished");
|
|
break;
|
|
} else {
|
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
|
board.board_hal.progress(chunk as u32).await;
|
|
board
|
|
.board_hal
|
|
.get_esp()
|
|
.write_file(filename.to_owned(), offset as u32, &buf)
|
|
.await?;
|
|
}
|
|
offset += buf.len();
|
|
chunk += 1;
|
|
}
|
|
BOARD_ACCESS
|
|
.get()
|
|
.await
|
|
.lock()
|
|
.await
|
|
.board_hal
|
|
.clear_progress()
|
|
.await;
|
|
conn.initiate_response(
|
|
200,
|
|
Some("OK"),
|
|
&[
|
|
("Access-Control-Allow-Origin", "*"),
|
|
("Access-Control-Allow-Headers", "*"),
|
|
("Access-Control-Allow-Methods", "*"),
|
|
],
|
|
)
|
|
.await?;
|
|
Some(200)
|
|
}
|
|
_ => None,
|
|
})
|
|
}
|