use crate::stream::{
FileStreamUpload, InitialStreamParams, STDIN_BUFFER_SIZE, Stream, complete_multipart_upload,
compress_chunk, create_initial_stream, get_key, initiate_multipart_upload, maybe_upload_part,
setup_stream_progress, upload_final_part, write_to_stream,
};
use anyhow::{Result, anyhow};
use futures::stream::TryStreamExt;
use tokio::fs::File;
use tokio_util::codec::{BytesCodec, FramedRead};
pub async fn stream_compressed(request: FileStreamUpload<'_>) -> Result<String> {
let FileStreamUpload {
s3,
object_key,
acl,
meta,
quiet,
tmp_dir,
globals,
file_path,
} = request;
let key = get_key(object_key, globals.compress, globals.encrypt);
let mut meta = meta.unwrap_or_default();
meta.insert("Content-Type".to_string(), "application/zstd".to_string());
let upload_id =
initiate_multipart_upload(s3, &key, acl, meta, globals.object_lock.clone()).await?;
let progress_sender = setup_stream_progress(quiet).await;
let first_stream: Stream = create_initial_stream(InitialStreamParams {
upload_id: &upload_id,
tmp_dir: &tmp_dir,
key: &key,
s3,
progress_sender,
globals: &globals,
header_data: None,
})?;
let file = File::open(file_path).await?;
let mut stream = FramedRead::new(file, BytesCodec::new())
.map_err(|e| anyhow!("Error reading file chunk: {e}"))
.try_fold(
first_stream,
|mut current_upload_state_acc, chunk| async move {
let compress_data = compress_chunk(chunk).await?;
write_to_stream(&mut current_upload_state_acc, &compress_data)
.map_err(|e| anyhow!("Error writing chunk to stream: {e}"))?;
maybe_upload_part(&mut current_upload_state_acc, STDIN_BUFFER_SIZE).await?;
Ok(current_upload_state_acc) },
)
.await?;
let final_etag = upload_final_part(&mut stream, &key, &upload_id, s3, &globals).await?;
stream.etags.push(final_etag);
if let Some(sender) = stream.channel.take() {
drop(sender);
}
complete_multipart_upload(s3, &key, &upload_id, stream.etags).await
}