69 lines
1.6 KiB
Rust
69 lines
1.6 KiB
Rust
use crate::*;
|
|
use blake2::{Blake2s256, Digest};
|
|
use lmdb::LmdbResultExt;
|
|
use lmdb_zero as lmdb;
|
|
use multipart::server::Multipart;
|
|
|
|
use std::io::Read;
|
|
use tiny_http::{Request, Response};
|
|
|
|
fn upload<'u>(
|
|
mut request: Request,
|
|
db_context: &DatabaseContext,
|
|
_: matchit::Params<'u, 'u>,
|
|
) -> CrowResult<()> {
|
|
let mut entry = some_or_response!(
|
|
single_multipart!(&mut request), or respond to request with Response::empty(400)
|
|
);
|
|
|
|
let mut data: Vec<u8> = Vec::with_capacity(20000);
|
|
entry.data.read_to_end(&mut data)?;
|
|
|
|
let data_hash = Blake2s256::digest(&data);
|
|
|
|
let txn = db_context.write_txn()?;
|
|
|
|
let mut accessor = txn.access();
|
|
|
|
if accessor
|
|
.get::<[u8], [u8]>(&db_context.binary_store, data_hash.as_slice())
|
|
.to_opt()?
|
|
.is_some()
|
|
{
|
|
request.respond(Response::from_string(base64_url::encode(&data_hash)))?;
|
|
return Ok(());
|
|
}
|
|
|
|
accessor.put(
|
|
&db_context.binary_store,
|
|
data_hash.as_slice(),
|
|
&data,
|
|
lmdb::put::Flags::empty(),
|
|
)?;
|
|
|
|
let header = FileHeader {
|
|
file_name: entry.headers.filename,
|
|
content_type: entry
|
|
.headers
|
|
.content_type
|
|
.map(|v| v.essence_str().to_owned()),
|
|
};
|
|
|
|
accessor.put(
|
|
&db_context.metadata_store,
|
|
data_hash.as_slice(),
|
|
rkyv::to_bytes::<_, 256>(&header).unwrap().as_slice(),
|
|
lmdb::put::Flags::empty(),
|
|
)?;
|
|
|
|
request.respond(Response::from_string(base64_url::encode(&data_hash)))?;
|
|
|
|
drop(accessor);
|
|
|
|
txn.commit()?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn_to_handler!(upload: UploadHandler);
|