GetLoanQuoteDocumentByIdQuery
Overview
The GetLoanQuoteDocumentByIdQuery retrieves a single document with its full content (base64 data) for download. Use this query when you need to download or display a specific document.
Handler File: CB.Administration.Api/Commands/BPM/SelfService/DocumentManagementCommand.cs
Use Cases
- Download document for viewing
- Export document to local file system
- Display document in PDF viewer
- Print document
- Forward document via email
Key Difference from GetLoanQuoteDocumentsQuery
| Query | Returns Data | Use Case |
|---|---|---|
| GetLoanQuoteDocumentsQuery | ❌ No | List documents (fast) |
| GetLoanQuoteDocumentByIdQuery | ✅ Yes | Download single document |
Request Parameters
Required Parameters
| Parameter | Type | Description |
|---|---|---|
loanQuoteId | long | The ID of the loan quote |
documentId | string (GUID) | The unique identifier of the document |
Request Example
{
"cmd": "GetLoanQuoteDocumentByIdQuery",
"data": {
"loanQuoteId": 110,
"documentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
Response Format
Success Response
{
"statusCode": "00",
"statusMessage": "SUCCESS",
"data": {
"documentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"documentName": "National ID Card.pdf",
"documentType": 1,
"documentTypeName": "NATIONAL_ID",
"description": "Customer national ID card - front and back",
"documentNumber": "ABC123456",
"documentExpiry": "2030-12-31T00:00:00Z",
"documentIssueDate": "2020-01-15T00:00:00Z",
"documentIssuer": "National Identity Management Commission",
"documentData": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlL...",
"createdDate": "2026-01-10T14:30:00Z",
"createdBy": {
"userId": 25,
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@bank.com"
}
}
}
Error Responses
Document Not Found:
{
"statusCode": "01",
"statusMessage": "Document not found for the specified loan quote",
"data": null
}
Invalid GUID Format:
{
"statusCode": "01",
"statusMessage": "Invalid documentId format",
"data": null
}
Loan Quote Not Found:
{
"statusCode": "01",
"statusMessage": "Loan quote with ID 999 not found",
"data": null
}
Response Fields
| Field | Type | Description |
|---|---|---|
documentId | string (GUID) | Unique identifier |
documentName | string | File name |
documentType | int | Document type enum |
documentTypeName | string | Type name |
description | string | Description |
documentNumber | string | Official number |
documentExpiry | DateTime | Expiration date |
documentIssueDate | DateTime | Issue date |
documentIssuer | string | Issuer |
documentData | string | Base64 encoded file content ✅ |
createdDate | DateTime | Upload timestamp |
createdBy | object | Uploader details |
JavaScript Usage Example
Download Document
const downloadDocument = async (loanQuoteId, documentId) => {
try {
const result = await api.query({
cmd: "GetLoanQuoteDocumentByIdQuery",
data: JSON.stringify({
loanQuoteId: loanQuoteId,
documentId: documentId
})
});
if (result.statusCode === "00") {
const doc = result.data;
// Convert base64 to blob
const blob = base64ToBlob(doc.documentData, getMimeType(doc.documentName));
// Create download link
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = doc.documentName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
// Clean up
URL.revokeObjectURL(url);
console.log("Document downloaded:", doc.documentName);
} else {
alert(`Error: ${result.statusMessage}`);
}
} catch (error) {
console.error("Download failed:", error);
alert("Failed to download document");
}
};
// Helper function to convert base64 to blob
const base64ToBlob = (base64, mimeType = 'application/octet-stream') => {
const byteCharacters = atob(base64);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
return new Blob([byteArray], { type: mimeType });
};
// Helper function to get MIME type from filename
const getMimeType = (filename) => {
const ext = filename.split('.').pop().toLowerCase();
const mimeTypes = {
'pdf': 'application/pdf',
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'png': 'image/png',
'doc': 'application/msword',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xls': 'application/vnd.ms-excel',
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
};
return mimeTypes[ext] || 'application/octet-stream';
};
Display PDF in Browser
const displayPdfInViewer = async (loanQuoteId, documentId) => {
try {
const result = await api.query({
cmd: "GetLoanQuoteDocumentByIdQuery",
data: JSON.stringify({ loanQuoteId, documentId })
});
if (result.statusCode === "00") {
const doc = result.data;
// Convert to blob URL
const blob = base64ToBlob(doc.documentData, 'application/pdf');
const url = URL.createObjectURL(blob);
// Display in iframe
const iframe = document.getElementById('pdfViewer');
iframe.src = url;
// Or open in new tab
// window.open(url, '_blank');
}
} catch (error) {
console.error("Display failed:", error);
}
};
Display Image Preview
const showImagePreview = async (loanQuoteId, documentId) => {
try {
const result = await api.query({
cmd: "GetLoanQuoteDocumentByIdQuery",
data: JSON.stringify({ loanQuoteId, documentId })
});
if (result.statusCode === "00") {
const doc = result.data;
// Create data URL
const mimeType = getMimeType(doc.documentName);
const dataUrl = `data:${mimeType};base64,${doc.documentData}`;
// Display in image element
const img = document.getElementById('documentPreview');
img.src = dataUrl;
img.alt = doc.documentName;
}
} catch (error) {
console.error("Preview failed:", error);
}
};
Complete Download Component
class DocumentDownloader {
constructor(loanQuoteId) {
this.loanQuoteId = loanQuoteId;
}
async download(documentId, documentName = null) {
try {
// Show loading indicator
this.showLoading(true);
const result = await api.query({
cmd: "GetLoanQuoteDocumentByIdQuery",
data: JSON.stringify({
loanQuoteId: this.loanQuoteId,
documentId: documentId
})
});
this.showLoading(false);
if (result.statusCode === "00") {
const doc = result.data;
this.triggerDownload(
doc.documentData,
documentName || doc.documentName
);
return true;
} else {
this.showError(result.statusMessage);
return false;
}
} catch (error) {
this.showLoading(false);
this.showError("Network error: " + error.message);
return false;
}
}
triggerDownload(base64Data, filename) {
const blob = this.base64ToBlob(base64Data, this.getMimeType(filename));
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
// Cleanup
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
}, 100);
}
base64ToBlob(base64, mimeType = 'application/octet-stream') {
const byteCharacters = atob(base64);
const byteArray = new Uint8Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteArray[i] = byteCharacters.charCodeAt(i);
}
return new Blob([byteArray], { type: mimeType });
}
getMimeType(filename) {
const ext = filename.split('.').pop().toLowerCase();
const types = {
'pdf': 'application/pdf',
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'png': 'image/png',
'gif': 'image/gif',
'doc': 'application/msword',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
};
return types[ext] || 'application/octet-stream';
}
showLoading(show) {
const spinner = document.getElementById('downloadSpinner');
if (spinner) {
spinner.style.display = show ? 'block' : 'none';
}
}
showError(message) {
alert(`Download Error: ${message}`);
}
}
// Usage
const downloader = new DocumentDownloader(110);
// In your button click handler
document.getElementById('downloadBtn').addEventListener('click', () => {
const documentId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";
downloader.download(documentId);
});
Validation Rules
- loanQuoteId: Must exist in database
- documentId: Must be valid GUID format
- Document Association: Document must be associated with the specified loan quote
Error Codes
| Status Code | Description |
|---|---|
| 00 | Success - document retrieved with data |
| 01 | Document not found |
| 01 | Invalid GUID format |
| 01 | Loan quote not found |
| 99 | General error |
Performance Considerations
- File Size: Larger files take longer to retrieve and transfer
- Base64 Overhead: ~33% larger than original file
- Network: Consider compression for large documents
- Caching: Cache document metadata, fetch data only when needed
Security Notes
- Validate user has permission to access the loan quote
- Validate user has permission to download documents
- Log all document downloads for audit
- Consider implementing download limits/throttling
- Scan downloaded files for viruses (client-side)
Related Commands
- GetLoanQuoteDocumentsQuery - List all documents (without data)
- CreateLoanQuoteDocumentCommand - Upload new document
Testing Checklist
- Download PDF document
- Download image document (JPEG, PNG)
- Download Office document (DOC, XLS)
- Test with invalid documentId
- Test with invalid GUID format
- Test with wrong loanQuoteId
- Verify documentData field is included
- Verify downloaded file opens correctly
- Test with large file (greater than 5MB)
- Test error handling for missing document
Browser Compatibility
The download implementation uses:
BlobAPI (IE 10 and above, all modern browsers)URL.createObjectURL()(IE 10 and above, all modern browsers)atob()for base64 decoding (IE 10 and above, all modern browsers)
For older browsers, consider using a polyfill like js-base64.