stream books instead of reading them into memory
This commit is contained in:
parent
d7f056f77e
commit
d00a7ef8dc
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1371,6 +1371,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"uuid",
|
||||
|
@ -17,6 +17,7 @@ tera = "1.19.1"
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true }
|
||||
tokio = { version = "1.37.0", features = ["rt-multi-thread", "macros"] }
|
||||
tokio-util = "0.7.11"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
uuid = { version = "1.8.0", features = ["v4", "fast-rng"] }
|
||||
|
@ -1,18 +1,22 @@
|
||||
//! Handle requests for specific formats of a book.
|
||||
|
||||
use std::{fs::File, io::Read, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
use tokio::fs::File;
|
||||
|
||||
use poem::{
|
||||
error::NotFoundError,
|
||||
handler,
|
||||
web::{Data, Path, WithContentType, WithHeader},
|
||||
IntoResponse,
|
||||
web::{Data, Path},
|
||||
Body, IntoResponse, Response,
|
||||
};
|
||||
use tokio_util::io::ReaderStream;
|
||||
|
||||
use crate::{
|
||||
app_state::AppState,
|
||||
data::book::{Book, Format},
|
||||
handlers::error::HandlerError,
|
||||
opds::media_type::MediaType,
|
||||
};
|
||||
|
||||
/// Handle a request for a book with id `id` in format `format`.
|
||||
@ -20,7 +24,7 @@ use crate::{
|
||||
pub async fn handler(
|
||||
Path((id, format)): Path<(u64, String)>,
|
||||
state: Data<&Arc<AppState>>,
|
||||
) -> Result<WithHeader<WithContentType<Vec<u8>>>, poem::Error> {
|
||||
) -> Result<Response, poem::Error> {
|
||||
let book = state
|
||||
.calibre
|
||||
.scalar_book(id)
|
||||
@ -33,13 +37,14 @@ pub async fn handler(
|
||||
.library_path
|
||||
.join(book.data.path)
|
||||
.join(file_name);
|
||||
let mut file = File::open(file_path).map_err(|_| NotFoundError)?;
|
||||
|
||||
let mut data = Vec::new();
|
||||
file.read_to_end(&mut data).map_err(|_| NotFoundError)?;
|
||||
let content_type = format.0;
|
||||
let mut file = File::open(file_path).await.map_err(|_| NotFoundError)?;
|
||||
let stream = ReaderStream::new(file);
|
||||
let body = Body::from_bytes_stream(stream);
|
||||
|
||||
Ok(data
|
||||
.with_content_type(content_type)
|
||||
.with_header("Content-Disposition", format!("filename={file_name};")))
|
||||
let content_type: MediaType = format.into();
|
||||
Ok(body
|
||||
.with_content_type(format!("{content_type}"))
|
||||
.with_header("Content-Disposition", format!("filename=\"{file_name}\""))
|
||||
.into_response())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user