-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Example for posting a body for AsyncRead? #879
Comments
For now I found that the best way is to use BytesCodec & FramedRead types from tokio-util crate. Internally it minimizes memory allocations, see an investigation here. So, full code will be: use reqwest::Body;
use tokio::fs::File;
use tokio_util::codec::{BytesCodec, FramedRead};
fn file_to_body(file: File) -> Body {
let stream = FramedRead::new(file, BytesCodec::new());
Body::wrap_stream(stream)
} |
Hi, @nbari, if you mean file uploading, here I've just tried to create Stream that consumes stream from FramedRead::new(file, BytesCodec::new()) and calls If you mean file downloading, just call |
Thanks, I am using this approach,
|
@nbari, I'm tried both approaches, but eventually decided that it is better to call Did you get smoothly increasing progress bar? |
Hi @nickkuk, I am currently working on it, indeed I am stuck with this, https://stackoverflow.com/q/63374041/1135424, any helps is pretty much appreciated.
I am getting:
But for other similar cases (multipart upload), I do get a nice progress bar: https://github.com/s3m/s3m/blob/develop/src/s3m/upload.rs#L55 |
I think you can use async_stream::stream! {
if let Some(mut sender) = sender {
while let Some(bytes) = stream.next().await {
if let Ok(bytes) = &bytes {
sender.send(bytes.len()).await;
}
yield bytes;
}
} else {
while let Some(bytes) = stream.next().await {
yield bytes;
}
}
} |
@nickkuk many thanks for the examples, I was indeed dealing with the
|
Hi @nickkuk I found interesting this example: use tokio::sync::mpsc;
use futures::future::Either;
fn upload(file: String, sender: Option<mpsc::Sender<usize>) {
let stream = FramedRead::new(file, BytesCodec::new());
let stream = if let Some(mut tx) = sender {
Either::Left(stream
.inspect_ok(move |chunk| tx.send(chunk.len()))
)
} else {
Either::Right(stream)
};
let body = Body::wrap_stream(stream);
} Is not clear for me why It won't compile if I don't add a
Also, I think it requires a
Just asking to understand & learn more, I indeed became curios because code for me looks cleaner when using Thanks in advance. |
From documentation of About
I suggest to use
|
Hi @nickkuk many thanks for the explanation and your time on this, taking advantage of the thread, I have one last question regarding this topic, probably too basic but hope you don't mind since I am trying to grasp the concepts of To increase the progress bar
Is think is the way to go, but now with too many new options that I just learn about how to do the same task but with different methods, I wonder if there is something more idiomatic to achieve the same. |
At first I want to clarify that in my last reply I suggested to use Actually you don't need any
For example, Main drawback of |
@nickkuk many thanks for the examples and sharing the knowledge, I highly appreciate it :-) |
Example for save a response body to file for async, and display download total progress? I don't know how to use buff to read and write let rsp = reqwest::Client::new().get("http://aabbcc.com/1.mp4").send().await;
let file = std::fs::File::create(file).unwrap();
let mut buf = [0; 8192];
let mut reader = StreamReader::new(rsp.bytes_stream());
loop {
// do read buff , write buff, print r/w size, util eof
} |
Hi people! I have the below code and I'm stucked because I don't know how to #[async_trait::async_trait]
impl Trait for UploadClient {
async fn put_file(
&self,
filename: &str,
mut reader: Pin<&mut (dyn AsyncRead + Send + Sync)>,
) -> Result<u64> {
// let url = ...;
let client = reqwest::Client::new();
let resp = client
.post(url)
// Nothing of these works!
// .body(reader)
// .body(reqwest::Body::wrap_stream(reader))
// .body(ReaderStream::new(reader))
.body(StreamReader::new(reader))
.send()
.await?
.error_for_status()?;
Ok(123)
}
} |
Hey @frederikhors, I think that the current standard approach is to use tokio-util helper crate with |
@frederikhors your example would not set the upload length though right ? There are a number of implementations of I am interested in this because i have a ProgressReader (reporting on upload progress) which is With some of the other examples above I am worried about backpressure and whether this is correctly handled. Based on the way async reads are handled I am pretty sure AsyncRead will always be pull based and thus handle pressure automatically. In general, tracking progress (optionally) for sending a request should be something built in. |
reqwest::blocking::Body
can be easily built from anyRead
object. I'm working on trying to convert some of this code to async, but can't for the life of me figure out how to do something similar in async land. I assume you have to usereqwest::Body::wrap_stream
, but how to create a proper stream from antokio::fs::AsyncRead
appears to be beyond me as I've been banging my head against this all day. It's easy enough to read the entireAsyncRead
into memory and provide it directly, but when uploading a file, that requires loading the entire file into memory. Any tips would be greatly appreciated, and since I doubt I'm the only one attempting this, perhaps adding an example of posting a file with the new async API would help a lot.Thanks!
The text was updated successfully, but these errors were encountered: