diff --git a/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte b/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte
index 7b12470d..9449026b 100644
--- a/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte
+++ b/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte
@@ -18,7 +18,7 @@
hosted_file_id: null | string;
hosted_file_obj: null | key_val;
filename?: null | string;
- max_length?: number;
+ max_filename?: number;
auto_download?: boolean;
linked_to_type?: null | string;
linked_to_id?: null | string;
@@ -28,16 +28,17 @@
variant?: 'tonal' | 'filled' | 'outline' | 'ghost';
color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error' | 'surface';
show_divider?: boolean;
+ show_direct_download?: boolean;
classes?: string;
label?: import('svelte').Snippet;
}
- let {
+ let {
log_lvl = 0,
hosted_file_id,
hosted_file_obj,
filename = $bindable(null),
- max_length = $bindable(30),
+ max_filename = $bindable(30),
auto_download = true,
linked_to_type = $bindable(null),
linked_to_id = $bindable(null),
@@ -47,6 +48,7 @@
variant = 'tonal',
color = 'primary',
show_divider = true,
+ show_direct_download = false,
classes = '',
label
}: Props = $props();
@@ -98,7 +100,7 @@
};
let variant_classes = $derived.by(() => {
- const base = 'btn btn-sm lg:btn-md min-w-48 transition-all overflow-hidden';
+ const base = 'btn btn-sm lg:btn-md min-w-48 transition-all overflow-hidden px-3';
const style = color_map[color]?.[variant] || color_map.primary.tonal;
return `${base} ${style} ${classes}`.trim();
});
@@ -151,109 +153,134 @@
}
};
});
+
+ let final_filename = $derived(filename ?? hosted_file_obj?.filename ?? 'unknown');
+ let shortened_filename = $derived(ae_util.shorten_filename({
+ filename: final_filename,
+ max_length: max_filename
+ }));
+
+ let direct_download_url = $derived.by(() => {
+ if (!show_direct_download || !hosted_file_obj) return '';
+ // IMPORTANT: For Direct Link Mode, we MUST use the V3 Action endpoint to support Random String IDs.
+ // Legacy endpoints often expect integer IDs and will return 404 for string IDs.
+ const file_id = hosted_file_obj.event_file_id || hosted_file_obj.hosted_file_id || hosted_file_id;
+ const obj_type_path = hosted_file_obj.event_file_id ? 'event_file' : 'hosted_file';
+ return `${$ae_api.base_url}/v3/action/${obj_type_path}/${file_id}/download?filename=${ae_util.clean_filename(final_filename)}&x_no_account_id_token=direct-download`;
+ });
-{#if hosted_file_id && hosted_file_obj}
- {@const file_id = hosted_file_obj.id || hosted_file_obj.hosted_file_id || hosted_file_id}
-
+ {/await}
+
+ {#if download_complete === null}
+ File not found
+ {:else if download_complete === false}
+ Failed!
+ {/if}
+{/snippet}
+
+{#if hosted_file_id && hosted_file_obj}
+ {@const file_id = hosted_file_obj.id || hosted_file_obj.hosted_file_id || hosted_file_id}
+
+ {#if show_direct_download}
+
+ {@render content()}
+
+ {:else}
+
+ {/if}
{:else}
-{/if}
+{/if}
\ No newline at end of file
diff --git a/src/lib/types/ae_types.ts b/src/lib/types/ae_types.ts
index d9aa7707..d00dced9 100644
--- a/src/lib/types/ae_types.ts
+++ b/src/lib/types/ae_types.ts
@@ -674,6 +674,8 @@ export interface ae_HostedFile extends ae_BaseObj {
hash_sha256?: string;
subdirectory_path?: string;
filename?: string;
+ filename_no_ext?: string;
+ filename_w_ext?: string;
extension?: string;
mimetype?: string;
size?: number;
diff --git a/src/routes/events/ae_comp__event_file_obj_tbl.svelte b/src/routes/events/ae_comp__event_file_obj_tbl.svelte
index 720d1263..a000d08a 100644
--- a/src/routes/events/ae_comp__event_file_obj_tbl.svelte
+++ b/src/routes/events/ae_comp__event_file_obj_tbl.svelte
@@ -375,24 +375,11 @@
Testing the AE_Comp_Hosted_Files_Download_Button component
@@ -103,6 +130,7 @@