Commit b110eb0e4d479472548896c41ca4c3445233348e
1 parent
eb9dfe04
Fixes #4 Basic upload endpoint done
Showing
9 changed files
with
76 additions
and
18 deletions
... | ... | @@ -25,17 +25,21 @@ edition = "2018" |
25 | 25 | |
26 | 26 | [dependencies] |
27 | 27 | actix-files = "0.2" |
28 | -actix-web = "2.0" | |
29 | 28 | actix-rt = "1.1.1" |
29 | +actix-web = "2.0" | |
30 | +anyhow = "1.0" | |
30 | 31 | artshop-common = { path = "../common" } |
32 | +async-std = "^1.10" | |
33 | +chrono = "0.4.15" | |
31 | 34 | diesel = { version = "1.4.7", features = ["sqlite", "r2d2"]} |
32 | -r2d2 = "0.8.9" | |
35 | +diffy = "0.2" | |
33 | 36 | dotenv = "0.15.0" |
37 | +flate2 = "^1.0" | |
38 | +futures = "^0.3" | |
39 | +listenfd = "0.3" | |
40 | +r2d2 = "0.8.9" | |
34 | 41 | serde = "1.0" |
35 | 42 | serde_derive = "1.0" |
36 | 43 | serde_json = "1.0" |
37 | -anyhow = "1.0" | |
38 | -chrono = "0.4.15" | |
39 | -listenfd = "0.3" | |
40 | -diffy = "0.2" | |
41 | -flate2 = "^1.0" | |
44 | +#tokio = { version = "1", features = ["full"] } | |
45 | +uuid = { version = "^0.8", features = ["v4"] } | ... | ... |
... | ... | @@ -15,6 +15,7 @@ use diesel::r2d2::{self, ConnectionManager}; |
15 | 15 | use diesel::SqliteConnection; |
16 | 16 | use listenfd::ListenFd; |
17 | 17 | use routes::markdown::get_markdown; |
18 | +use routes::upload::upload; | |
18 | 19 | |
19 | 20 | pub(crate) type Pool = r2d2::Pool<ConnectionManager<SqliteConnection>>; |
20 | 21 | |
... | ... | @@ -33,6 +34,9 @@ async fn main() -> std::io::Result<()> { |
33 | 34 | App::new() . data(database_pool.clone()) |
34 | 35 | . service(actix_files::Files::new("/static", "./static")) |
35 | 36 | . service( web::scope("/api/v0") |
37 | + . service( web::resource("/upload") | |
38 | + . route(web::post().to(upload)) | |
39 | + ) | |
36 | 40 | . service( web::resource("/markdowns") |
37 | 41 | . route(web::get().to(get_markdowns)) |
38 | 42 | ) | ... | ... |
server/src/routes/upload.rs
0 → 100644
1 | +use actix_web::{Error, HttpResponse, web}; | |
2 | +use anyhow::Result; | |
3 | +use futures::stream::StreamExt; | |
4 | +use async_std::{fs::OpenOptions, io::WriteExt}; | |
5 | +use uuid::Uuid; | |
6 | + | |
7 | +pub async fn upload(mut body: web::Payload) -> Result<HttpResponse, Error> | |
8 | +{ | |
9 | + let mut output = OpenOptions::new(); | |
10 | + output . create(true) | |
11 | + . write(true); | |
12 | + let mut output = output | |
13 | + . open(format!("/tmp/upload_{}", Uuid::new_v4())) | |
14 | + . await | |
15 | + . unwrap(); | |
16 | + | |
17 | + while let Some(item) = body.next().await { | |
18 | + output.write_all(&item?).await.unwrap(); | |
19 | + } | |
20 | + | |
21 | + Ok(HttpResponse::Ok().finish()) | |
22 | +} | ... | ... |
... | ... | @@ -18,6 +18,7 @@ impl UploadApi { |
18 | 18 | pub(crate) async fn store(&self, upload :&Upload) -> Result<&UploadApi> { |
19 | 19 | let response = self.client.post_stream( "/api/v0/upload" |
20 | 20 | , &upload.mime_type() |
21 | + , upload.size() | |
21 | 22 | , upload.data() ).await?; |
22 | 23 | match response.status() { |
23 | 24 | 200 => Ok(self), | ... | ... |
1 | 1 | use js_sys::JsString; |
2 | 2 | use mogwai::prelude::*; |
3 | 3 | use wasm_bindgen::prelude::*; |
4 | -use web_sys::{Window, window, Response, Request, RequestInit, RequestMode, ReadableStream}; | |
4 | +use web_sys::{Window, window, Response, Request, RequestInit, RequestMode, Headers}; | |
5 | 5 | use super::error::*; |
6 | 6 | |
7 | 7 | use std::result::Result as StdResult; |
... | ... | @@ -63,17 +63,20 @@ impl Client { |
63 | 63 | } |
64 | 64 | |
65 | 65 | pub async fn post_stream( &self |
66 | - , url :&str | |
66 | + , url :&str | |
67 | 67 | , mime_type :&str |
68 | - , data :ReadableStream) -> Result<Response> { | |
68 | + , length :usize | |
69 | + , data :&JsValue ) -> Result<Response> { | |
70 | + let headers = Headers::new()?; | |
71 | + headers.set("Content-Type", mime_type)?; | |
72 | + headers.set("Content-Length", &format!("{}", length))?; | |
73 | + | |
69 | 74 | let mut init = RequestInit::new(); |
70 | 75 | let request = REQUEST( url |
71 | 76 | , init . method("POST") |
72 | 77 | . mode(RequestMode::Cors) |
73 | - . body(Some(&data.into())) )?; | |
74 | - | |
75 | - request . headers() | |
76 | - . set("Content-Type", mime_type)?; | |
78 | + . headers(&headers.into()) | |
79 | + . body(Some(data)) )?; | |
77 | 80 | |
78 | 81 | let response = JsFuture::from( self.window |
79 | 82 | . fetch_with_request(&request)) | ... | ... |
... | ... | @@ -85,12 +85,29 @@ pub(super) async fn upload_logic( mut rx_logic :broadcast::Receiver<UploadLogic> |
85 | 85 | } |
86 | 86 | }, |
87 | 87 | UploadLogic::Upload => { |
88 | + let mut remove_ids = vec![]; | |
89 | + | |
88 | 90 | for upload in uploads.read().await.iter() { |
89 | 91 | match api.store(upload).await { |
90 | - Ok(_) => (), | |
92 | + Ok(_) => remove_ids.push(upload.id), | |
91 | 93 | Err(e) => log::error!("{:?}", e), |
92 | 94 | } |
93 | 95 | } |
96 | + | |
97 | + for id in remove_ids.iter() { | |
98 | + let mut found = None; | |
99 | + | |
100 | + for (upload, index) in uploads.read().await.iter().zip(0..) { | |
101 | + if upload.id == *id { | |
102 | + found = Some(index); | |
103 | + break; | |
104 | + } | |
105 | + } | |
106 | + | |
107 | + if let Some(index) = found { | |
108 | + uploads.list_patch_remove(index).unwrap(); | |
109 | + } | |
110 | + } | |
94 | 111 | } |
95 | 112 | } |
96 | 113 | } | ... | ... |
1 | 1 | use mogwai::{prelude::*, utils::window}; |
2 | -use web_sys::{File, ImageBitmap, ReadableStream}; | |
2 | +use web_sys::{File, ImageBitmap}; | |
3 | +use wasm_bindgen::prelude::*; | |
3 | 4 | |
4 | 5 | use super::{view::upload_preview_view, logic::{upload_preview_logic, UploadLogic}}; |
5 | 6 | |
... | ... | @@ -30,8 +31,12 @@ impl Upload { |
30 | 31 | self.file.type_() |
31 | 32 | } |
32 | 33 | |
33 | - pub(crate) fn data(&self) -> ReadableStream { | |
34 | - self.file.stream() | |
34 | + pub(crate) fn data(&self) -> &JsValue { | |
35 | + &self.file | |
36 | + } | |
37 | + | |
38 | + pub(crate) fn size(&self) -> usize { | |
39 | + self.file.size() as usize | |
35 | 40 | } |
36 | 41 | |
37 | 42 | pub(super) fn bitmap(&self) -> ImageBitmap { | ... | ... |
Please
register
or
login
to post a comment