pub struct FileStream<S> {
pub stream: S,
pub file_name: Option<String>,
pub content_size: Option<u64>,
}
Available on crate feature
file-stream
only.Expand description
Encapsulate the file stream.
The encapsulated file stream construct requires passing in a stream.
§Examples
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
routing::get,
Router,
};
use axum_extra::response::file_stream::FileStream;
use tokio::fs::File;
use tokio_util::io::ReaderStream;
async fn file_stream() -> Result<Response, (StatusCode, String)> {
let file = File::open("test.txt")
.await
.map_err(|e| (StatusCode::NOT_FOUND, format!("File not found: {e}")))?;
let stream = ReaderStream::new(file);
let file_stream_resp = FileStream::new(stream).file_name("test.txt");
Ok(file_stream_resp.into_response())
}
let app = Router::new().route("/file-stream", get(file_stream));
Fields§
§stream: S
stream.
file_name: Option<String>
The file name of the file.
content_size: Option<u64>
The size of the file.
Implementations§
Source§impl<S> FileStream<S>
impl<S> FileStream<S>
Sourcepub fn new(stream: S) -> Self
pub fn new(stream: S) -> Self
Create a new FileStream
Sourcepub async fn from_path(
path: impl AsRef<Path>,
) -> Result<FileStream<ReaderStream<File>>>
pub async fn from_path( path: impl AsRef<Path>, ) -> Result<FileStream<ReaderStream<File>>>
Create a FileStream
from a file path.
§Examples
use axum::{
http::StatusCode,
response::IntoResponse,
Router,
routing::get
};
use axum_extra::response::file_stream::FileStream;
use tokio::fs::File;
use tokio_util::io::ReaderStream;
async fn file_stream() -> impl IntoResponse {
FileStream::<ReaderStream<File>>::from_path("test.txt")
.await
.map_err(|e| (StatusCode::NOT_FOUND, format!("File not found: {e}")))
}
let app = Router::new().route("/file-stream", get(file_stream));
Sourcepub fn file_name(self, file_name: impl Into<String>) -> Self
pub fn file_name(self, file_name: impl Into<String>) -> Self
Set the file name of the FileStream
.
This adds the attachment Content-Disposition
header with the given file_name
.
Sourcepub fn content_size(self, len: u64) -> Self
pub fn content_size(self, len: u64) -> Self
Set the size of the file.
Sourcepub fn into_range_response(
self,
start: u64,
end: u64,
total_size: u64,
) -> Response
pub fn into_range_response( self, start: u64, end: u64, total_size: u64, ) -> Response
Return a range response.
range: (start, end, total_size)
§Examples
use axum::{
http::StatusCode,
response::IntoResponse,
routing::get,
Router,
};
use axum_extra::response::file_stream::FileStream;
use tokio::fs::File;
use tokio::io::AsyncSeekExt;
use tokio_util::io::ReaderStream;
async fn range_response() -> Result<impl IntoResponse, (StatusCode, String)> {
let mut file = File::open("test.txt")
.await
.map_err(|e| (StatusCode::NOT_FOUND, format!("File not found: {e}")))?;
let mut file_size = file
.metadata()
.await
.map_err(|e| (StatusCode::NOT_FOUND, format!("Get file size: {e}")))?
.len();
file.seek(std::io::SeekFrom::Start(10))
.await
.map_err(|e| (StatusCode::NOT_FOUND, format!("File seek error: {e}")))?;
let stream = ReaderStream::new(file);
Ok(FileStream::new(stream).into_range_response(10, file_size - 1, file_size))
}
let app = Router::new().route("/file-stream", get(range_response));
Sourcepub async fn try_range_response(
file_path: impl AsRef<Path>,
start: u64,
end: u64,
) -> Result<Response>
pub async fn try_range_response( file_path: impl AsRef<Path>, start: u64, end: u64, ) -> Result<Response>
Attempts to return RANGE requests directly from the file path.
§Arguments
file_path
- The path of the file to be streamedstart
- The start position of the rangeend
- The end position of the range
§Note
- If
end
is 0, then it is used asfile_size - 1
- If
start
>file_size
orstart
>end
, thenRange Not Satisfiable
is returned
§Examples
use axum::{
http::StatusCode,
response::IntoResponse,
Router,
routing::get
};
use std::path::Path;
use axum_extra::response::file_stream::FileStream;
use tokio::fs::File;
use tokio_util::io::ReaderStream;
use tokio::io::AsyncSeekExt;
async fn range_stream() -> impl IntoResponse {
let range_start = 0;
let range_end = 1024;
FileStream::<ReaderStream<File>>::try_range_response("CHANGELOG.md", range_start, range_end).await
.map_err(|e| (StatusCode::NOT_FOUND, format!("File not found: {e}")))
}
let app = Router::new().route("/file-stream", get(range_stream));
Trait Implementations§
Source§impl<S: Debug> Debug for FileStream<S>
impl<S: Debug> Debug for FileStream<S>
Auto Trait Implementations§
impl<S> Freeze for FileStream<S>where
S: Freeze,
impl<S> RefUnwindSafe for FileStream<S>where
S: RefUnwindSafe,
impl<S> Send for FileStream<S>where
S: Send,
impl<S> Sync for FileStream<S>where
S: Sync,
impl<S> Unpin for FileStream<S>where
S: Unpin,
impl<S> UnwindSafe for FileStream<S>where
S: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more