11use crate :: constants:: TAG ;
2- use crate :: error:: AppResult ;
3- use crate :: logging:: android_log;
2+ use crate :: error:: { AppError , AppResult } ;
43use crate :: models:: { GroupRepoMediaPath , GroupRepoPath } ;
54use crate :: server:: server:: get_backend;
65use crate :: utils:: create_veilid_cryptokey_from_base64;
7- use crate :: { log_debug, log_info} ;
8- use actix_web:: web:: Bytes ;
9- use actix_web:: { delete, get, post, web, HttpResponse , Responder , Scope } ;
6+ use crate :: log_info;
7+ use actix_web:: { delete, get, post, web, HttpResponse , Responder , Scope , http:: header, error:: BlockingError } ;
8+ use bytes:: { BytesMut , Bytes } ;
9+ use futures:: Stream ;
1010use futures:: StreamExt ;
11- use save_dweb_backend:: common:: DHTEntity ;
1211use serde_json:: json;
12+ use std:: io;
1313
1414pub fn scope ( ) -> Scope {
1515 web:: scope ( "/media" )
@@ -19,6 +19,27 @@ pub fn scope() -> Scope {
1919 . service ( download_file)
2020}
2121
22+ pub fn from_blocking < T > ( result : Result < T , BlockingError > ) -> AppResult < T > {
23+ result. map_err ( AppError :: from)
24+ }
25+
26+ async fn handle_file_stream ( mut file_data : impl Stream < Item = Result < Bytes , io:: Error > > + Unpin ) -> AppResult < ( usize , Bytes ) > {
27+ let mut buffer = BytesMut :: new ( ) ;
28+ let mut length = 0 ;
29+
30+ while let Some ( chunk_result) = file_data. next ( ) . await {
31+ let chunk = chunk_result. map_err ( |e| AppError ( anyhow:: Error :: new ( e) ) ) ?;
32+ buffer. extend_from_slice ( & chunk) ;
33+ length += chunk. len ( ) ;
34+ }
35+
36+ let final_buffer = web:: block ( move || {
37+ buffer. freeze ( )
38+ } ) . await ?;
39+
40+ Ok ( ( length, final_buffer) )
41+ }
42+
2243#[ get( "" ) ]
2344async fn list_files ( path : web:: Path < GroupRepoPath > ) -> AppResult < impl Responder > {
2445 let path_params = path. into_inner ( ) ;
@@ -55,8 +76,7 @@ async fn list_files(path: web::Path<GroupRepoPath>) -> AppResult<impl Responder>
5576 "is_downloaded" : is_downloaded
5677 } ) ) ;
5778 }
58-
59- Ok ( HttpResponse :: Ok ( ) . json ( files_with_status) )
79+ Ok ( HttpResponse :: Ok ( ) . json ( json ! ( { "files" : files_with_status } ) ) )
6080}
6181
6282#[ get( "/{file_name}" ) ]
@@ -93,13 +113,14 @@ async fn download_file(path: web::Path<GroupRepoMediaPath>) -> AppResult<impl Re
93113 // Trigger file download from peers using the hash
94114 let file_data = repo
95115 . get_file_stream ( file_name)
96- . await
97- . map_err ( |e| anyhow:: anyhow!( "Failed to download file from peers: {}" , e) ) ?;
116+ . await ?;
117+
118+ let ( content_length, buffered_data) = handle_file_stream ( file_data) . await ?;
98119
99- // Return the file data as a binary response
100120 Ok ( HttpResponse :: Ok ( )
101121 . content_type ( "application/octet-stream" )
102- . streaming ( file_data) )
122+ . insert_header ( ( header:: CONTENT_LENGTH , content_length) )
123+ . body ( buffered_data) )
103124}
104125
105126#[ delete( "/{file_name}" ) ]
@@ -175,6 +196,7 @@ async fn upload_file(
175196 . map_err ( |e| anyhow:: anyhow!( "Failed to upload file: {}" , e) ) ?;
176197
177198 Ok ( HttpResponse :: Ok ( ) . json ( json ! ( {
199+ "name" : file_name,
178200 "updated_collection_hash" : updated_collection_hash,
179201 } ) ) )
180202}
0 commit comments