Template-driven folder and filename generation from 18 system tokens. Two-phase resolution for pre-save uploads.
Edit the fields below to watch the resolved folder path and filename update in real time. All 18 system tokens plus dynamic context tokens are shown.
IAttachmentPathResolutionService.ResolvePhase2Async()
calls SP_ATTACHMENT_GET_DEFERRED → IStorageProvider.MoveAsync() → SP_ATTACHMENT_UPDATE_RESOLVED_PATH (TVP bulk update).
Seven steps from file stream to TATTACHMENT row. MD5 is computed in BLL before the stream is consumed by storage.
// AttachmentOptionType from IStorageProvider.ProviderType private static byte ProviderToOption(StorageProviderType p) => p switch { StorageProviderType.S3 => 2, // AmazonS3 StorageProviderType.Network => 3, // FileBased _ => 3 }; // MD5 computed before storage consumes the stream using var ms = new MemoryStream(); await fileStream.CopyToAsync(ms, ct).ConfigureAwait(false); Span<byte> hash = stackalloc byte[16]; MD5.HashData(ms.GetBuffer().AsSpan(0, (int)ms.Length), hash); var contentHash = Convert.ToHexString(hash).ToLowerInvariant();
Files uploaded before entity save use a RowGuid as the ObjectId placeholder. Phase 2 atomically moves the files and updates TATTACHMENT within the entity save transaction.
Legacy Alfresco attachments have no TATTACHMENT rows. Migration discovers them via CMIS API, downloads, saves to new storage, and inserts rows — one ObjectTypeId at a time.
Two modes delegate to the same IAttachmentUploadService — all template resolution, MD5, and TATTACHMENT insertion follow the identical path as a single upload.
manifest.csv found at source folder root or path explicitly provided.FilePath,ObjectTypeId,ObjectId,DocSetDetailId,... /import/po_1201.pdf,101,1201,4,Vendor Quote /import/po_1201_inv.pdf,101,1201,5,Invoice
MENTITY.ENTITYCODE./attachments/
PURCHASEORDER/ ← EntityCode
1201/ ← ObjectId
quote.pdf
invoice.pdf
TBULK_INGESTION_JOB. Final status = Done (2) if any files succeeded; Failed (3) only if all files failed.
Resolved by SystemTokenResolver. Context tokens (dot-notation) resolved by DictionaryTokenResolver from the request's ContextDictionary.
| Token | Source | Example | Notes |
|---|---|---|---|
| _tenantCode | MCLIENT.CLIENTCODE | ACME | Sanitised |
| _tenantName | MCLIENT.CLIENTNAME | Acme Corp | Sanitised |
| _year | UploadedOn.Year | 2026 | |
| _month | UploadedOn.Month | 07 | 2-digit padded |
| _yyyymm | UploadedOn | 202607 | |
| _yyyymmdd | UploadedOn | 20260704 | |
| _moduleCode | Template.ModuleCode | MM | From SP_ATTACHMENT_LOAD_TEMPLATE |
| _moduleName | Template.ModuleName | Materials | |
| _entityCode | MENTITY.ENTITYCODE | PURCHASEORDER | |
| _entityName | MENTITY.ENTITYNAME | Purchase Order | |
| _docTypeCode | Template.DocumentTypeCode | VQ | |
| _docTypeName | Template.DocumentTypeName | Vendor Quote | |
| _docSetCode | Template.DocumentSetCode | DS_PO_001 | |
| _slNo | Context.SlNo | 001 | 3-digit padded |
| _version | Context.Version | 1 | |
| _ext | FileExtension | No dot, lowercased | |
| _objectId | Context.ObjectId (or RowGuid in Phase 1) | 12345 or a3f91b2c... | Phase 1: RowGuid placeholder |
| _rowGuid | Context.RowGuid | a3f91b2c-d4e5... | FE-generated UUID |
| {custom.key} | ContextDictionary | PO-2026-0842 | Dot-notation; e.g. vendor.vendorCode |