Download an object from S3 and return its content.
Downloads the specified object from S3 using an HTTP GET request via curl. The content is returned as an allocatable string. Works with both public and authenticated buckets.
@param[in] key The S3 object key (path within the bucket) @param[out] content The downloaded content as an allocatable string @return .true. if download succeeded, .false. on error
Note
The module must be initialized with s3_init() before calling this function.
Warning
Returns .false. if the module is not initialized or if the download fails.
character(len=:), allocatable :: content
logical :: success
success = s3_get_object('data/input.txt', content)
if (success) then
print *, 'Downloaded: ', len(content), ' bytes'
print *, content
else
print *, 'Download failed'
end if
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
character(len=*), | intent(in) | :: | key | |||
character(len=:), | intent(out), | allocatable | :: | content |
function s3_get_object(key, content) result(success) character(len=*), intent(in) :: key character(len=:), allocatable, intent(out) :: content logical :: success character(len=2048) :: url character(len=4096) :: cmd integer :: exit_status character(len=2048) :: msg success = .false. if (.not. initialized) then call s3_log_error('s3_get_object called before s3_init()') return end if ! Log key (truncated if too long for buffer) if (len_trim(key) <= 2030) then ! "Getting object: " is 17 chars write(msg, '(A,A)') 'Getting object: ', trim(key) else write(msg, '(A,A,A)') 'Getting object: ', key(1:2020), '...' end if call s3_log_info(trim(msg)) ! Build URL if (current_config%use_https) then write(url, '(A,A,A,A,A,A)') 'https://', & trim(current_config%bucket), '.', & trim(current_config%endpoint), '/', & trim(key) else write(url, '(A,A,A,A,A,A)') 'http://', & trim(current_config%bucket), '.', & trim(current_config%endpoint), '/', & trim(key) end if write(msg, '(A,A)') 'URL: ', trim(url) call s3_log_debug(trim(msg)) ! Build curl command write(cmd, '(A,A,A)') 'curl -s "', trim(url), '"' write(msg, '(A,A)') 'Command: ', trim(cmd) call s3_log_trace(trim(msg)) ! Try streaming first (if available), fall back to temp file if (is_streaming_available()) then call s3_log_debug('Attempting direct streaming') ! Use direct streaming (no disk I/O) success = stream_command_output(trim(cmd), content, exit_status) if (success .and. exit_status == 0) then write(msg, '(A,I0,A)') 'Streaming successful, received ', len(content), ' bytes' call s3_log_debug(trim(msg)) ! Check for S3 error in response if (index(content, '<Error>') > 0) then call s3_log_error('S3 error detected in response') if (len(content) < 500) then call s3_log_debug('Response: ' // content) else call s3_log_debug('Response (first 500 chars): ' // content(1:500)) end if success = .false. end if return else write(msg, '(A,I0)') 'Streaming failed with exit status: ', exit_status call s3_log_warn(trim(msg)) end if else call s3_log_info('Streaming not available, using temp file method') end if ! Fallback to temp file method (for Windows or if streaming fails) call s3_log_debug('Falling back to temp file method') success = s3_get_object_fallback(key, content) end function s3_get_object