|
| 1 | +[](https://github.com/routerify/routerify-multipart/actions) |
| 2 | +[](https://crates.io/crates/routerify-multipart) |
| 3 | +[](https://docs.rs/routerify-multipart) |
| 4 | +[](./LICENSE) |
| 5 | + |
1 | 6 | # routerify-multipart |
2 | | -A multipart/form-data parser for Routerify |
| 7 | + |
| 8 | +A `multipart/form-data` parser for [`Routerify`](https://github.com/routerify/routerify). |
| 9 | + |
| 10 | +[Docs](https://docs.rs/routerify-multipart) |
| 11 | + |
| 12 | +## Install |
| 13 | + |
| 14 | +Add this to your `Cargo.toml` file: |
| 15 | + |
| 16 | +```toml |
| 17 | +[dependencies] |
| 18 | +routerify = "1.1" |
| 19 | +routerify-multipart = "1.0" |
| 20 | +``` |
| 21 | + |
| 22 | +## Example |
| 23 | + |
| 24 | +```rust |
| 25 | +use hyper::{Body, Request, Response, Server, StatusCode}; |
| 26 | +use routerify::{Error, Router, RouterService}; |
| 27 | +// Import `RequestMultipartExt` trait. |
| 28 | +use routerify_multipart::RequestMultipartExt; |
| 29 | +use std::net::SocketAddr; |
| 30 | + |
| 31 | +// A handler to handle file uploading in `multipart/form-data` content-type. |
| 32 | +async fn file_upload_handler(req: Request<Body>) -> Result<Response<Body>, Error> { |
| 33 | + // Convert the request into a `Multipart` instance. |
| 34 | + let mut multipart = match req.into_multipart() { |
| 35 | + Ok(m) => m, |
| 36 | + Err(err) => { |
| 37 | + return Ok(Response::builder() |
| 38 | + .status(StatusCode::BAD_REQUEST) |
| 39 | + .body(Body::from(format!("Bad Request: {}", err))) |
| 40 | + .unwrap()); |
| 41 | + } |
| 42 | + }; |
| 43 | + |
| 44 | + // Iterate over the fields. |
| 45 | + while let Some(mut field) = multipart.next_field().await.map_err(|err| Error::wrap(err))? { |
| 46 | + // Get the field name. |
| 47 | + let name = field.name(); |
| 48 | + // Get the field's filename if provided in "Content-Disposition" header. |
| 49 | + let file_name = field.file_name(); |
| 50 | + |
| 51 | + println!("Name {:?}, File name: {:?}", name, file_name); |
| 52 | + |
| 53 | + // Process the field data chunks e.g. store them in a file. |
| 54 | + while let Some(chunk) = field.chunk().await.map_err(|err| Error::wrap(err))? { |
| 55 | + // Do something with field chunk. |
| 56 | + println!("Chunk: {:?}", chunk); |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + Ok(Response::new(Body::from("Success"))) |
| 61 | +} |
| 62 | + |
| 63 | +// Create a router. |
| 64 | +fn router() -> Router<Body, Error> { |
| 65 | + // Register the handlers. |
| 66 | + Router::builder().post("/upload", file_upload_handler).build().unwrap() |
| 67 | +} |
| 68 | + |
| 69 | +#[tokio::main] |
| 70 | +async fn main() { |
| 71 | + let router = router(); |
| 72 | + |
| 73 | + // Create a Service from the router above to handle incoming requests. |
| 74 | + let service = RouterService::new(router).unwrap(); |
| 75 | + |
| 76 | + // The address on which the server will be listening. |
| 77 | + let addr = SocketAddr::from(([127, 0, 0, 1], 3001)); |
| 78 | + |
| 79 | + // Create a server by passing the created service to `.serve` method. |
| 80 | + let server = Server::bind(&addr).serve(service); |
| 81 | + |
| 82 | + println!("App is running on: {}", addr); |
| 83 | + if let Err(err) = server.await { |
| 84 | + eprintln!("Server error: {}", err); |
| 85 | + } |
| 86 | +} |
| 87 | +``` |
| 88 | + |
| 89 | +## Contributing |
| 90 | + |
| 91 | +Your PRs and suggestions are always welcome. |
0 commit comments