opendal/services/seafile/
writer.rs1use std::sync::Arc;
19
20use http::header;
21use http::Request;
22use http::StatusCode;
23
24use super::core::SeafileCore;
25use super::error::parse_error;
26use crate::raw::*;
27use crate::*;
28
29pub type SeafileWriters = oio::OneShotWriter<SeafileWriter>;
30
31pub struct SeafileWriter {
32 core: Arc<SeafileCore>,
33 _op: OpWrite,
34 path: String,
35}
36
37impl SeafileWriter {
38 pub fn new(core: Arc<SeafileCore>, op: OpWrite, path: String) -> Self {
39 SeafileWriter {
40 core,
41 _op: op,
42 path,
43 }
44 }
45}
46
47impl oio::OneShotWrite for SeafileWriter {
48 async fn write_once(&self, bs: Buffer) -> Result<Metadata> {
49 let upload_url = self.core.get_upload_url().await?;
50
51 let req = Request::post(upload_url);
52
53 let (filename, relative_path) = if self.path.ends_with('/') {
54 ("", build_abs_path(&self.core.root, &self.path))
55 } else {
56 let (filename, relative_path) = (get_basename(&self.path), get_parent(&self.path));
57 (filename, build_abs_path(&self.core.root, relative_path))
58 };
59
60 let file_part = FormDataPart::new("file")
61 .header(
62 header::CONTENT_DISPOSITION,
63 format!("form-data; name=\"file\"; filename=\"{filename}\"")
64 .parse()
65 .unwrap(),
66 )
67 .content(bs);
68
69 let multipart = Multipart::new()
70 .part(FormDataPart::new("parent_dir").content("/"))
71 .part(FormDataPart::new("relative_path").content(relative_path.clone()))
72 .part(FormDataPart::new("replace").content("1"))
73 .part(file_part);
74
75 let req = multipart.apply(req)?;
76
77 let resp = self.core.send(req).await?;
78
79 let status = resp.status();
80
81 match status {
82 StatusCode::OK => Ok(Metadata::default()),
83 _ => Err(parse_error(resp)),
84 }
85 }
86}