1

I modified a mini server with "use std::net::TcpListener; use std::net::TcpStream;" from the Rust Book example (https://doc.rust-lang.org/book/ch20-03-graceful-shutdown-and-cleanup.html).

This code works from Firefox browser common "form" sending a "input type='file'" with obviously "'enctype='multipart/form-data'":

let mut datax = Vec::new(); let mut el_buffer = [0; 1024]; let mut limita = 0; loop { let n = stream.read(&mut el_buffer).unwrap(); if n<1024 { datax.extend_from_slice(&el_buffer[..n]); break; } else { datax.extend_from_slice(&el_buffer[..n]); } if limita >10000 { break; } limita += 1; } 

I tried: read_to_end(); read_exact(); BufReader::new(&stream); let mut el_buffer = [0; 1024]; // 1, 512, 4092, 10240, 102400, 2000 etc.
I tried "n==0... break"
I tried read without loop...

The result is the same:
From Firefox read all the file and works.
From Edge, Chrome, IE, cuts the POST received and the browser loses the server connection.

0

2 Answers 2

2
 if n<1024 { datax.extend_from_slice(&el_buffer[..n]); break; } else { 

Read::read() returning a number less than the full size does not mean that the end of the input has been reached. It could mean the data is not yet available (e.g. the browser has not yet sent it) or it could be for any whim of the kernel.

You should end your reading loop when read() returns zero. That is the only return value which is specified to mean “end of file”.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, very good explanation about "read()" works but if change to "if n==0 {" the stream enter in a never ending loop.
@navetix That is probably because in modern HTTP, the browser is allowed to keep the connection open — so there is no end-of-file to look for in that case. You need to use the data in the Content-Length and Content-Transfer-Encoding request headers to determine where the end of the body is.
Really thanks Mr. Kevin for your interest. I think I use the headers well including "Content-length"... The funny thing is that a long time ago I started with the same project but in Python language and it was the same problem XD... I think problem is in "read()" because if I "print" buffer chunk the browser send headers but not binary data, but in Firefox yes. Any other idea please?
0

After much try and error, googling, try and error, googling... I found an excellent explanation and that is "read()" function is not enough to handle bytes in "stream" so I find great tool called "buf_redux" which replaces the standard tool "std::io::BufReader". I used it like this:

In "Cargo.toml":

[dependencies] buf_redux = "0.8.4" 

In "main.rs"

 use buf_redux::BufReader; // .... let mut datax = Vec::new(); let mut el_buffer = [0; 4096]; // A 10 MBytes aprox.: let mut lector = BufReader::with_capacity(10240000, &mut stream); loop { let n = lector.read(&mut el_buffer).unwrap(); println!("Bytes : {:?}", n); if n<4096 { datax.extend_from_slice(&el_buffer[..n]); break; } else { datax.extend_from_slice(&el_buffer[..n]); } } 

I hope it helps someone

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.