@@ -140,6 +140,75 @@ export class S3AttachmentManager extends BaseAttachmentManager {
140140 } ;
141141 }
142142
143+ /**
144+ * Get file metadata by ID.
145+ *
146+ * For S3, this requires fetching the object metadata from S3.
147+ * The fileId is used to reconstruct the S3 key.
148+ *
149+ * Note: This implementation retrieves basic metadata from S3.
150+ * The checksum is retrieved from object metadata if available.
151+ *
152+ * @param fileId - The unique identifier of the file
153+ * @returns The file metadata or null if not found
154+ */
155+ async getFile ( fileId : string ) : Promise < AttachmentFileRecord | null > {
156+ try {
157+ // For S3, we need to list objects with the fileId prefix to find the actual key
158+ const prefix = `${ this . keyPrefix } ${ fileId } /` ;
159+
160+ // Import HeadObjectCommand for metadata retrieval
161+ const { HeadObjectCommand } = await import ( '@aws-sdk/client-s3' ) ;
162+ const { ListObjectsV2Command } = await import ( '@aws-sdk/client-s3' ) ;
163+
164+ // List objects with the fileId prefix
165+ const listCommand = new ListObjectsV2Command ( {
166+ Bucket : this . bucket ,
167+ Prefix : prefix ,
168+ MaxKeys : 1 ,
169+ } ) ;
170+
171+ const listResponse = await this . s3Client . send ( listCommand ) ;
172+
173+ if ( ! listResponse . Contents || listResponse . Contents . length === 0 ) {
174+ return null ;
175+ }
176+
177+ const key = listResponse . Contents [ 0 ] . Key ;
178+ if ( ! key ) {
179+ return null ;
180+ }
181+
182+ // Get detailed metadata
183+ const headCommand = new HeadObjectCommand ( {
184+ Bucket : this . bucket ,
185+ Key : key ,
186+ } ) ;
187+
188+ const headResponse = await this . s3Client . send ( headCommand ) ;
189+
190+ const filename = headResponse . Metadata ?. originalFilename || key . split ( '/' ) . pop ( ) || 'unknown' ;
191+ const checksum = headResponse . Metadata ?. checksum || '' ;
192+
193+ return {
194+ id : fileId ,
195+ filename,
196+ contentType : headResponse . ContentType || 'application/octet-stream' ,
197+ size : headResponse . ContentLength || 0 ,
198+ checksum,
199+ storageMetadata : {
200+ bucket : this . bucket ,
201+ key,
202+ region : this . s3Client . config . region ,
203+ } ,
204+ createdAt : headResponse . LastModified || new Date ( ) ,
205+ updatedAt : headResponse . LastModified || new Date ( ) ,
206+ } ;
207+ } catch ( error ) {
208+ return null ;
209+ }
210+ }
211+
143212 /**
144213 * Reconstruct an AttachmentFile accessor from storage metadata.
145214 *
0 commit comments