Kaynağa Gözat

Fetch metadata only once when downloading

timvisee 7 yıl önce
ebeveyn
işleme
d3f1288824
2 değiştirilmiş dosya ile 26 ekleme ve 13 silme
  1. 25 13
      api/src/action/download.rs
  2. 1 0
      cli/src/action/download.rs

+ 25 - 13
api/src/action/download.rs

@@ -20,6 +20,7 @@ use reader::{EncryptedFileWriter, ProgressReporter, ProgressWriter};
 use super::metadata::{
 use super::metadata::{
     Error as MetadataError,
     Error as MetadataError,
     Metadata as MetadataAction,
     Metadata as MetadataAction,
+    MetadataResponse,
 };
 };
 
 
 /// A file upload action to a Send server.
 /// A file upload action to a Send server.
@@ -35,6 +36,10 @@ pub struct Download<'a> {
 
 
     /// Check whether the file exists (recommended).
     /// Check whether the file exists (recommended).
     check_exists: bool,
     check_exists: bool,
+
+    /// The metadata response to work with,
+    /// which will skip the internal metadata request.
+    metadata_response: Option<MetadataResponse>,
 }
 }
 
 
 impl<'a> Download<'a> {
 impl<'a> Download<'a> {
@@ -46,36 +51,43 @@ impl<'a> Download<'a> {
         target: PathBuf,
         target: PathBuf,
         password: Option<String>,
         password: Option<String>,
         check_exists: bool,
         check_exists: bool,
+        metadata_response: Option<MetadataResponse>,
     ) -> Self {
     ) -> Self {
         Self {
         Self {
             file,
             file,
             target,
             target,
             password,
             password,
             check_exists,
             check_exists,
+            metadata_response,
         }
         }
     }
     }
 
 
     /// Invoke the download action.
     /// Invoke the download action.
     pub fn invoke(
     pub fn invoke(
-        self,
+        mut self,
         client: &Client,
         client: &Client,
         reporter: Arc<Mutex<ProgressReporter>>,
         reporter: Arc<Mutex<ProgressReporter>>,
     ) -> Result<(), Error> {
     ) -> Result<(), Error> {
         // Create a key set for the file
         // Create a key set for the file
         let mut key = KeySet::from(self.file, self.password.as_ref());
         let mut key = KeySet::from(self.file, self.password.as_ref());
 
 
-        // Fetch the file metadata, update the input vector in the key set
-        let metadata = MetadataAction::new(
-                self.file,
-                self.password.clone(),
-                self.check_exists,
-            )
-            .invoke(&client)
-            .map_err(|err| match err {
-                MetadataError::PasswordRequired => Error::PasswordRequired,
-                MetadataError::Expired => Error::Expired,
-                _ => err.into(),
-            })?;
+        // Get the metadata, or fetch the file metadata,
+        // then update the input vector in the key set
+        let metadata: MetadataResponse = if self.metadata_response.is_some() {
+                self.metadata_response.take().unwrap()
+            } else {
+                MetadataAction::new(
+                        self.file,
+                        self.password.clone(),
+                        self.check_exists,
+                    )
+                    .invoke(&client)
+                    .map_err(|err| match err {
+                        MetadataError::PasswordRequired => Error::PasswordRequired,
+                        MetadataError::Expired => Error::Expired,
+                        _ => err.into(),
+                    })?
+            };
         key.set_iv(metadata.metadata().iv());
         key.set_iv(metadata.metadata().iv());
 
 
         // Decide what actual file target to use
         // Decide what actual file target to use

+ 1 - 0
cli/src/action/download.rs

@@ -93,6 +93,7 @@ impl<'a> Download<'a> {
             target,
             target,
             password,
             password,
             false,
             false,
+            Some(metadata),
         ).invoke(&client, bar)?;
         ).invoke(&client, bar)?;
 
 
         // TODO: open the file, or it's location
         // TODO: open the file, or it's location