mirror of
https://github.com/timvisee/ffsend.git
synced 2025-10-06 02:29:57 +02:00
Complete upload progress bar implementation, simplify with arc/mutex
This commit is contained in:
parent
030454cc10
commit
b57e85a8ec
4 changed files with 29 additions and 20 deletions
|
@ -1,6 +1,7 @@
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use mime_guess::{get_mime_type, Mime};
|
use mime_guess::{get_mime_type, Mime};
|
||||||
use openssl::symm::encrypt_aead;
|
use openssl::symm::encrypt_aead;
|
||||||
|
@ -24,8 +25,7 @@ use reader::{
|
||||||
use file::file::File as SendFile;
|
use file::file::File as SendFile;
|
||||||
use file::metadata::{Metadata, XFileMetadata};
|
use file::metadata::{Metadata, XFileMetadata};
|
||||||
|
|
||||||
type EncryptedReader =
|
type EncryptedReader = ProgressReader<BufReader<EncryptedFileReaderTagged>>;
|
||||||
ProgressReader<'static, BufReader<EncryptedFileReaderTagged>>;
|
|
||||||
pub type Result<T> = ::std::result::Result<T, UploadError>;
|
pub type Result<T> = ::std::result::Result<T, UploadError>;
|
||||||
|
|
||||||
/// A file upload action to a Send server.
|
/// A file upload action to a Send server.
|
||||||
|
@ -50,7 +50,7 @@ impl Upload {
|
||||||
pub fn invoke(
|
pub fn invoke(
|
||||||
self,
|
self,
|
||||||
client: &Client,
|
client: &Client,
|
||||||
reporter: Box<ProgressReporter + 'static>,
|
reporter: Arc<Mutex<ProgressReporter>>,
|
||||||
) -> Result<SendFile> {
|
) -> Result<SendFile> {
|
||||||
// Create file data, generate a key
|
// Create file data, generate a key
|
||||||
let file = FileData::from(Box::new(&self.path))?;
|
let file = FileData::from(Box::new(&self.path))?;
|
||||||
|
@ -58,8 +58,8 @@ impl Upload {
|
||||||
|
|
||||||
// Crpate metadata and a file reader
|
// Crpate metadata and a file reader
|
||||||
let metadata = self.create_metadata(&key, &file)?;
|
let metadata = self.create_metadata(&key, &file)?;
|
||||||
// TODO: do not use leak, as it might cause memory leaks
|
let reader = self.create_reader(&key, reporter.clone())?;
|
||||||
let reader = self.create_reader(&key, Box::leak(reporter))?;
|
let reader_len = reader.len().unwrap();
|
||||||
|
|
||||||
// Create the request to send
|
// Create the request to send
|
||||||
let req = self.create_request(
|
let req = self.create_request(
|
||||||
|
@ -69,10 +69,18 @@ impl Upload {
|
||||||
reader,
|
reader,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Start the reporter
|
||||||
|
reporter.lock()
|
||||||
|
.expect("unable to start progress, failed to get lock")
|
||||||
|
.start(reader_len);
|
||||||
|
|
||||||
// Execute the request
|
// Execute the request
|
||||||
let result = self.execute_request(req, client, &key);
|
let result = self.execute_request(req, client, &key);
|
||||||
|
|
||||||
// TODO: finish the progress bar
|
// Mark the reporter as finished
|
||||||
|
reporter.lock()
|
||||||
|
.expect("unable to finish progress, failed to get lock")
|
||||||
|
.finish();
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -112,7 +120,7 @@ impl Upload {
|
||||||
fn create_reader(
|
fn create_reader(
|
||||||
&self,
|
&self,
|
||||||
key: &KeySet,
|
key: &KeySet,
|
||||||
reporter: &'static mut ProgressReporter,
|
reporter: Arc<Mutex<ProgressReporter>>,
|
||||||
) -> Result<EncryptedReader> {
|
) -> Result<EncryptedReader> {
|
||||||
// Open the file
|
// Open the file
|
||||||
let file = match File::open(self.path.as_path()) {
|
let file = match File::open(self.path.as_path()) {
|
||||||
|
@ -139,8 +147,7 @@ impl Upload {
|
||||||
.expect("failed to create progress reader");
|
.expect("failed to create progress reader");
|
||||||
|
|
||||||
// Initialize and attach the reporter
|
// Initialize and attach the reporter
|
||||||
reporter.start(reader.len().unwrap());
|
reader.set_reporter(reporter);
|
||||||
reader.set_reporter(&mut *reporter);
|
|
||||||
|
|
||||||
Ok(reader)
|
Ok(reader)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::io::{
|
||||||
Error as IoError,
|
Error as IoError,
|
||||||
Read,
|
Read,
|
||||||
};
|
};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use openssl::symm::{
|
use openssl::symm::{
|
||||||
Cipher,
|
Cipher,
|
||||||
|
@ -236,7 +237,7 @@ unsafe impl Send for EncryptedFileReaderTagged {}
|
||||||
///
|
///
|
||||||
/// The reader will only start producing `None` if the wrapped reader is doing
|
/// The reader will only start producing `None` if the wrapped reader is doing
|
||||||
/// so.
|
/// so.
|
||||||
pub struct ProgressReader<'a, R> {
|
pub struct ProgressReader<R> {
|
||||||
/// The wrapped reader.
|
/// The wrapped reader.
|
||||||
inner: R,
|
inner: R,
|
||||||
|
|
||||||
|
@ -247,10 +248,10 @@ pub struct ProgressReader<'a, R> {
|
||||||
progress: u64,
|
progress: u64,
|
||||||
|
|
||||||
/// A reporter, to report the progress status to.
|
/// A reporter, to report the progress status to.
|
||||||
reporter: Option<&'a mut ProgressReporter>,
|
reporter: Option<Arc<Mutex<ProgressReporter>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: Read> ProgressReader<'a, R> {
|
impl<R: Read> ProgressReader<R> {
|
||||||
/// Wrap the given reader with an exact length, in a progress reader.
|
/// Wrap the given reader with an exact length, in a progress reader.
|
||||||
pub fn new(inner: R) -> Result<Self, IoError>
|
pub fn new(inner: R) -> Result<Self, IoError>
|
||||||
where
|
where
|
||||||
|
@ -277,7 +278,7 @@ impl<'a, R: Read> ProgressReader<'a, R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the reporter to report the status to.
|
/// Set the reporter to report the status to.
|
||||||
pub fn set_reporter(&mut self, reporter: &'a mut ProgressReporter) {
|
pub fn set_reporter(&mut self, reporter: Arc<Mutex<ProgressReporter>>) {
|
||||||
self.reporter = Some(reporter);
|
self.reporter = Some(reporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +288,7 @@ impl<'a, R: Read> ProgressReader<'a, R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: Read> Read for ProgressReader<'a, R> {
|
impl<R: Read> Read for ProgressReader<R> {
|
||||||
/// Read from the encrypted file, and then the encryption tag.
|
/// Read from the encrypted file, and then the encryption tag.
|
||||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
|
||||||
// Read from the wrapped reader, increase the progress
|
// Read from the wrapped reader, increase the progress
|
||||||
|
@ -301,14 +302,16 @@ impl<'a, R: Read> Read for ProgressReader<'a, R> {
|
||||||
|
|
||||||
// Report
|
// Report
|
||||||
if let Some(reporter) = self.reporter.as_mut() {
|
if let Some(reporter) = self.reporter.as_mut() {
|
||||||
reporter.progress(self.progress);
|
reporter.lock()
|
||||||
|
.expect("failed to update progress, unable to lock reproter")
|
||||||
|
.progress(self.progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: Read> ExactLengthReader for ProgressReader<'a, R> {
|
impl<R: Read> ExactLengthReader for ProgressReader<R> {
|
||||||
// Return the specified length.
|
// Return the specified length.
|
||||||
fn len(&self) -> Result<u64, io::Error> {
|
fn len(&self) -> Result<u64, io::Error> {
|
||||||
Ok(self.len)
|
Ok(self.len)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use ffsend_api::action::upload::Upload as ApiUpload;
|
use ffsend_api::action::upload::Upload as ApiUpload;
|
||||||
use ffsend_api::reqwest::Client;
|
use ffsend_api::reqwest::Client;
|
||||||
|
@ -34,7 +34,7 @@ impl<'a> Upload<'a> {
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
|
|
||||||
// Create a progress bar reporter
|
// Create a progress bar reporter
|
||||||
let bar = Box::new(ProgressBar::new());
|
let bar = Arc::new(Mutex::new(ProgressBar::new()));
|
||||||
|
|
||||||
// Execute an upload action
|
// Execute an upload action
|
||||||
// TODO: do not unwrap, but return an error
|
// TODO: do not unwrap, but return an error
|
||||||
|
|
|
@ -42,7 +42,6 @@ impl ProgressReporter for ProgressBar {
|
||||||
fn finish(&mut self) {
|
fn finish(&mut self) {
|
||||||
self.bar.as_mut()
|
self.bar.as_mut()
|
||||||
.expect("progress bar not yet instantiated")
|
.expect("progress bar not yet instantiated")
|
||||||
// TODO: print a proper message here
|
.finish_print("File uploaded");
|
||||||
.finish_print("DONE");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue