Merge pull request #277 from dvdsk/streaming_file_up_down

Awnser Range requests and stream files downloads
This commit is contained in:
Dániel Szabó 2024-10-24 13:48:41 +09:00 committed by GitHub
commit d3a7eaf072
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 24 deletions

View file

@ -70,6 +70,10 @@ pub fn expiration_to_timestamp(expiration: &str, timenow: i64) -> i64 {
}
}
/// receives a file through http Post on url /upload/a-b-c with a, b and c
/// different animals. The client sends the post in response to a form.
// TODO: form field order might need to be changed. In my testing the attachment
// data is nestled between password encryption key etc <21-10-24, dvdsk>
pub async fn create(
data: web::Data<AppState>,
mut payload: Multipart,

View file

@ -1,4 +1,4 @@
use std::fs::{self, File};
use std::fs::File;
use std::path::PathBuf;
use crate::args::ARGS;
@ -8,6 +8,7 @@ use crate::util::misc::remove_expired;
use crate::util::{animalnumbers::to_u64, misc::decrypt_file};
use crate::AppState;
use actix_multipart::Multipart;
use actix_web::http::header;
use actix_web::{get, post, web, Error, HttpResponse};
#[post("/secure_file/{id}")]
@ -49,6 +50,8 @@ pub async fn post_secure_file(
pastas[index].id_as_animals()
))?;
// Not compatible with NamedFile from actix_files (it needs a File
// to work therefore secure files do not support streaming
let decrypted_data: Vec<u8> = decrypt_file(&password, &file)?;
// Set the content type based on the file extension
@ -63,6 +66,7 @@ pub async fn post_secure_file(
"Content-Disposition",
format!("attachment; filename=\"{}\"", pasta_file.name()),
))
// TODO: make streaming <21-10-24, dvdsk>
.body(decrypted_data);
return Ok(response);
}
@ -72,8 +76,9 @@ pub async fn post_secure_file(
#[get("/file/{id}")]
pub async fn get_file(
data: web::Data<AppState>,
request: actix_web::HttpRequest,
id: web::Path<String>,
data: web::Data<AppState>,
) -> Result<HttpResponse, Error> {
// get access to the pasta collection
let mut pastas = data.pastas.lock().unwrap();
@ -118,28 +123,18 @@ pub async fn get_file(
);
let file_path = PathBuf::from(file_path);
// Read the contents of the file into memory
// let mut file_content = Vec::new();
// let mut file = File::open(&file_path)?;
// file.read_exact(&mut file_content)?;
let file_contents = fs::read(&file_path)?;
// Set the content type based on the file extension
let content_type = mime_guess::from_path(&file_path)
.first_or_octet_stream()
.to_string();
// Create an HttpResponse object with the file contents as the response body
let response = HttpResponse::Ok()
.content_type(content_type)
.append_header((
"Content-Disposition",
format!("attachment; filename=\"{}\"", pasta_file.name()),
))
.body(file_contents);
return Ok(response);
// This will stream the file and set the content type based on the
// file path
let file_reponse = actix_files::NamedFile::open(file_path)?;
let file_reponse = file_reponse.set_content_disposition(header::ContentDisposition {
disposition: header::DispositionType::Attachment,
parameters: vec![header::DispositionParam::Filename(
pasta_file.name().to_string(),
)],
});
// This takes care of streaming/seeking using the Range
// header in the request.
return Ok(file_reponse.into_response(&request));
}
}