Add size and modified date
This commit is contained in:
parent
3ebb73959b
commit
161f4f1b1d
|
@ -763,6 +763,12 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "human-size"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9994b79e8c1a39b3166c63ae7823bb2b00831e2a96a31399c50fe69df408eaeb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humansize"
|
name = "humansize"
|
||||||
version = "2.1.3"
|
version = "2.1.3"
|
||||||
|
@ -1979,10 +1985,12 @@ name = "serves3"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"config",
|
"config",
|
||||||
|
"human-size",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_dyn_templates",
|
"rocket_dyn_templates",
|
||||||
"rust-s3",
|
"rust-s3",
|
||||||
|
"serde",
|
||||||
"tempdir",
|
"tempdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,10 @@ license = "EUPL-1.2"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
config = "0.13"
|
config = "0.13"
|
||||||
|
human-size = "0.4"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "v0.5.0-rc.3" }
|
rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "v0.5.0-rc.3" }
|
||||||
rocket_dyn_templates = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "v0.5.0-rc.3", features = ["tera"] }
|
rocket_dyn_templates = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "v0.5.0-rc.3", features = ["tera"] }
|
||||||
rust-s3 = { version = "0.32", default-features = false, features = ["tokio-rustls-tls"] }
|
rust-s3 = { version = "0.32", default-features = false, features = ["tokio-rustls-tls"] }
|
||||||
tempdir = "0.3"
|
serde = { version = "1.0" }
|
||||||
|
tempdir = { version = "0.3" }
|
||||||
|
|
64
src/main.rs
64
src/main.rs
|
@ -4,6 +4,7 @@
|
||||||
use {
|
use {
|
||||||
lazy_static::lazy_static,
|
lazy_static::lazy_static,
|
||||||
rocket::response::Responder,
|
rocket::response::Responder,
|
||||||
|
rocket::serde::Serialize,
|
||||||
rocket_dyn_templates::{context, Template},
|
rocket_dyn_templates::{context, Template},
|
||||||
std::path::PathBuf,
|
std::path::PathBuf,
|
||||||
};
|
};
|
||||||
|
@ -75,6 +76,14 @@ enum FileView {
|
||||||
File(Vec<u8>),
|
File(Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct FileViewItem {
|
||||||
|
path: String,
|
||||||
|
size: String,
|
||||||
|
size_bytes: u64,
|
||||||
|
last_modification: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Responder, Debug)]
|
#[derive(Responder, Debug)]
|
||||||
enum Error {
|
enum Error {
|
||||||
#[response(status = 404)]
|
#[response(status = 404)]
|
||||||
|
@ -136,7 +145,7 @@ async fn s3_serve_file(path: &PathBuf) -> Result<FileView, Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn s3_fileview(path: &PathBuf) -> Result<Vec<String>, Error> {
|
async fn s3_fileview(path: &PathBuf) -> Result<Vec<FileViewItem>, Error> {
|
||||||
/*
|
/*
|
||||||
if listing a folder:
|
if listing a folder:
|
||||||
- folders will be under 'common_prefixes'
|
- folders will be under 'common_prefixes'
|
||||||
|
@ -156,33 +165,64 @@ async fn s3_fileview(path: &PathBuf) -> Result<Vec<String>, Error> {
|
||||||
|
|
||||||
let objects = s3_objects
|
let objects = s3_objects
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|list| -> Vec<Option<&str>> {
|
.flat_map(|list| -> Vec<Option<FileViewItem>> {
|
||||||
let prefix = if let Some(p) = &list.prefix {
|
let prefix = if let Some(p) = &list.prefix {
|
||||||
p.as_str()
|
p.as_str()
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
let folders = list
|
let folders = list.common_prefixes.iter().flatten().map(|dir| {
|
||||||
.common_prefixes
|
let path = dir.prefix.strip_prefix(&prefix);
|
||||||
.iter()
|
path.map(|path| FileViewItem {
|
||||||
.flatten()
|
path: path.to_owned(),
|
||||||
.map(|dir| dir.prefix.strip_prefix(&prefix));
|
size_bytes: 0,
|
||||||
|
size: "[DIR]".to_owned(),
|
||||||
|
last_modification: String::default(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
let files = list
|
let files = list.contents.iter().map(|obj| {
|
||||||
.contents
|
let path = obj.key.strip_prefix(&prefix);
|
||||||
.iter()
|
path.map(|path| FileViewItem {
|
||||||
.map(|obj| obj.key.strip_prefix(&prefix));
|
path: path.to_owned(),
|
||||||
|
size_bytes: obj.size,
|
||||||
|
size: size_bytes_to_human(obj.size),
|
||||||
|
last_modification: obj.last_modified.clone(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
folders.chain(files).collect()
|
folders.chain(files).collect()
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(str::to_owned)
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(objects)
|
Ok(objects)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn size_bytes_to_human(bytes: u64) -> String {
|
||||||
|
use human_size::{Any, SpecificSize};
|
||||||
|
|
||||||
|
let size: f64 = bytes as f64;
|
||||||
|
let digits = size.log10().floor() as u32;
|
||||||
|
let mut order = digits / 3;
|
||||||
|
let unit = match order {
|
||||||
|
0 => Any::Byte,
|
||||||
|
1 => Any::Kilobyte,
|
||||||
|
2 => Any::Megabyte,
|
||||||
|
_ => {
|
||||||
|
order = 3; // Let's stop here.
|
||||||
|
Any::Gigabyte
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"{:.3}",
|
||||||
|
SpecificSize::new(size / 10u64.pow(order * 3) as f64, unit)
|
||||||
|
.unwrap_or(SpecificSize::new(0., Any::Byte).unwrap())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[rocket::launch]
|
#[rocket::launch]
|
||||||
fn rocket() -> _ {
|
fn rocket() -> _ {
|
||||||
eprintln!("Proxying to {} for {}", BUCKET.host(), BUCKET.name());
|
eprintln!("Proxying to {} for {}", BUCKET.host(), BUCKET.name());
|
||||||
|
|
|
@ -4,17 +4,53 @@
|
||||||
SPDX-License-Identifier: EUPL-1.2
|
SPDX-License-Identifier: EUPL-1.2
|
||||||
-->
|
-->
|
||||||
<html>
|
<html>
|
||||||
<head></head>
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: .3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead th {
|
||||||
|
border-bottom: 1px dotted black;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>{{ path }}</h1>
|
<h1>{{ path }}</h1>
|
||||||
<ul>
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Filename</th>
|
||||||
|
<th scope="col">Size</th>
|
||||||
|
<th scope="col">Modified</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{% if path != "/" %}
|
{% if path != "/" %}
|
||||||
<li><a href="../">..</a></li>
|
<tr>
|
||||||
|
<td><a href="../">..</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for object in objects %}
|
{% for object in objects %}
|
||||||
<li><a href="{{ object | urlencode }}">{{ object }}</a></li>
|
<tr>
|
||||||
|
<td><a href="{{ object.path | urlencode }}" data-size-bytes="{{ object.size_bytes }}">{{ object.path }}</a></td>
|
||||||
|
<td>{{ object.size }}</td>
|
||||||
|
<td>{{ object.last_modification}}</td>
|
||||||
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html
|
</html
|
||||||
|
|
Loading…
Reference in New Issue