Skip to content

Commit

Permalink
Corrected the features format, the example creates the file first to …
Browse files Browse the repository at this point in the history
…test it.
  • Loading branch information
YanHeDoki committed Nov 26, 2024
1 parent 1f2d314 commit f3fd30b
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 20 deletions.
4 changes: 2 additions & 2 deletions axum-extra/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ version = "0.10.0-alpha.1"
default = ["tracing", "multipart"]

async-read-body = ["dep:tokio-util", "tokio-util?/io", "dep:tokio"]
fileStream = ["dep:tokio-util", "tokio-util?/io", "dep:tokio"]
file-stream = ["dep:tokio-util", "tokio-util?/io", "dep:tokio"]
attachment = ["dep:tracing"]
error_response = ["dep:tracing", "tracing/std"]
cookie = ["dep:cookie"]
Expand Down Expand Up @@ -68,7 +68,7 @@ prost = { version = "0.13", optional = true }
serde_html_form = { version = "0.2.0", optional = true }
serde_json = { version = "1.0.71", optional = true }
serde_path_to_error = { version = "0.1.8", optional = true }
tokio = { version = "1.19", optional = true }
tokio = { version = "1.19", optional = true, features = ["fs"] }
tokio-stream = { version = "0.1.9", optional = true }
tokio-util = { version = "0.7", optional = true }
tracing = { version = "0.1.37", default-features = false, optional = true }
Expand Down
15 changes: 7 additions & 8 deletions axum-extra/src/response/file_stream.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::{io, path::PathBuf};

use axum::{
body,
response::{IntoResponse, Response},
Expand All @@ -8,6 +6,7 @@ use axum::{
use bytes::Bytes;
use futures_util::TryStream;
use http::{header, StatusCode};
use std::{io, path::PathBuf};
use tokio::fs::File;
use tokio_util::io::ReaderStream;

Expand Down Expand Up @@ -79,13 +78,13 @@ where
/// };
/// use axum_extra::response::file_stream::FileStream;
/// use std::path::PathBuf;
/// use tokio_util::io::ReaderStream;
/// use tokio::fs::File;
/// async fn file_stream() -> Result<Response, (StatusCode, String)> {
/// Ok(FileStream::<ReaderStream<File>>::from_path(PathBuf::from("test.txt"))
/// use tokio_util::io::ReaderStream;
/// async fn file_stream() -> Response {
/// FileStream::<ReaderStream<File>>::from_path(PathBuf::from("test.txt"))
/// .await
/// .map_err(|e| (StatusCode::NOT_FOUND, format!("File not found: {e}")))?
/// .into_response())
/// .map_err(|e| (StatusCode::NOT_FOUND, format!("File not found: {e}")))
/// .into_response()
/// }
/// let app = Router::new().route("/FileStreamDownload", get(file_stream));
/// # let _: Router = app;
Expand Down Expand Up @@ -253,7 +252,7 @@ mod tests {
"attachment; filename=\"CHANGELOG.md\""
);

let file = tokio::fs::File::open("CHANGELOG.md").await.unwrap();
let file = File::open("CHANGELOG.md").await.unwrap();
// get file size
let content_length = file.metadata().await.unwrap().len();

Expand Down
2 changes: 1 addition & 1 deletion axum-extra/src/response/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub mod multiple;
#[cfg(feature = "error_response")]
mod error_response;

#[cfg(feature = "fileStream")]
#[cfg(feature = "file-stream")]
/// Module for handling file streams.
pub mod file_stream;

Expand Down
2 changes: 1 addition & 1 deletion examples/stream-to-file/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ publish = false
[dependencies]
async-stream = "0.3"
axum = { path = "../../axum", features = ["multipart"] }
axum-extra = { path = "../../axum-extra", features = ["fileStream"] }
axum-extra = { path = "../../axum-extra", features = ["file-stream"] }
futures = "0.3"
tokio = { version = "1.0", features = ["full"] }
tokio-util = { version = "0.7", features = ["io"] }
Expand Down
41 changes: 33 additions & 8 deletions examples/stream-to-file/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ use axum::{
};
use axum_extra::response::file_stream::{AsyncReaderStream, FileStream};
use futures::{Stream, TryStreamExt};
use std::io;
use std::{io, path::PathBuf};
use tokio::{
fs::File,
io::{AsyncReadExt, AsyncSeekExt, BufWriter},
io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, BufWriter},
};
use tokio_util::io::StreamReader;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
const UPLOADS_DIRECTORY: &str = "uploads";

const DOWNLOAD_DIRECTORY: &str = "downloads";
#[tokio::main]
async fn main() {
tracing_subscriber::registry()
Expand All @@ -39,6 +39,15 @@ async fn main() {
.await
.expect("failed to create `uploads` directory");

tokio::fs::create_dir(DOWNLOAD_DIRECTORY)
.await
.expect("failed to create `downloads` directory");

//create a file to download
create_test_file(std::path::Path::new(DOWNLOAD_DIRECTORY).join("test.txt"))
.await
.expect("failed to create test file");

let app = Router::new()
.route("/upload", get(show_form).post(accept_form))
.route("/", get(show_form2).post(accept_form))
Expand All @@ -53,6 +62,19 @@ async fn main() {
axum::serve(listener, app).await.unwrap();
}

async fn create_test_file(path: PathBuf) -> io::Result<()> {
let mut file = File::create(path).await?;
for i in 1..=30 {
let line = format!(
"Hello, this is the simulated file content! This is line {}\n",
i
);
file.write_all(line.as_bytes()).await?;
}
file.flush().await?;
Ok(())
}

// Handler that streams the request body to a file.
//
// POST'ing to `/file/foo.txt` will create a file called `foo.txt`.
Expand Down Expand Up @@ -135,16 +157,19 @@ async fn show_form2() -> Html<&'static str> {
async fn simpler_file_download_handler() -> Response {
//If you want to simply return a file as a stream
// you can use the from_path method directly, passing in the path of the file to construct a stream with a header and length.
FileStream::<AsyncReaderStream>::from_path("./CHANGELOG.md".into())
.await
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "Failed to open file").into_response())
.into_response()
FileStream::<AsyncReaderStream>::from_path(
std::path::Path::new(DOWNLOAD_DIRECTORY).join("test.txt"),
)
.await
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "Failed to open file").into_response())
.into_response()
}

/// If you want to control the returned files in more detail you can implement a Stream
/// For example, use the try_stream! macro to construct a file stream and set which parts are needed.
async fn file_download_handler() -> Response {
let file_stream = match try_stream("./CHANGELOG.md", 5, 25, 10).await {
let file_path = format!("{DOWNLOAD_DIRECTORY}/test.txt");
let file_stream = match try_stream(&file_path, 5, 25, 10).await {
Ok(file_stream) => file_stream,
Err(e) => {
println!("{e}");
Expand Down

0 comments on commit f3fd30b

Please sign in to comment.