0
# Attachments & Files
1
2
The Attachments & Files module provides comprehensive file management capabilities for CRM records, including file upload, download, attachment management, and file organization.
3
4
## Capabilities
5
6
### Attachments Operations
7
8
Complete attachment management for CRM records.
9
10
```javascript { .api }
11
/**
12
* Operations for managing file attachments on CRM records
13
*/
14
class AttachmentsOperations {
15
/**
16
* Download a specific attachment from a record
17
* @param moduleAPIName - API name of the CRM module
18
* @param recordId - ID of the record containing the attachment
19
* @param attachmentId - ID of the attachment to download
20
* @returns Promise with APIResponse containing file data
21
*/
22
downloadAttachment(moduleAPIName: string, recordId: BigInt, attachmentId: BigInt): Promise<APIResponse>;
23
24
/**
25
* Delete a specific attachment from a record
26
* @param moduleAPIName - API name of the CRM module
27
* @param recordId - ID of the record containing the attachment
28
* @param attachmentId - ID of the attachment to delete
29
* @returns Promise with APIResponse containing deletion results
30
*/
31
deleteAttachment(moduleAPIName: string, recordId: BigInt, attachmentId: BigInt): Promise<APIResponse>;
32
33
/**
34
* Upload a file as an attachment to a record
35
* @param moduleAPIName - API name of the CRM module
36
* @param recordId - ID of the record to attach the file to
37
* @param request - File body wrapper containing the file to upload
38
* @returns Promise with APIResponse containing upload results
39
*/
40
uploadAttachment(moduleAPIName: string, recordId: BigInt, request: FileBodyWrapper): Promise<APIResponse>;
41
42
/**
43
* Get list of attachments for a specific record
44
* @param moduleAPIName - API name of the CRM module
45
* @param recordId - ID of the record
46
* @param paramInstance - Optional parameters for filtering and pagination
47
* @returns Promise with APIResponse containing attachment list
48
*/
49
getAttachments(moduleAPIName: string, recordId: BigInt, paramInstance?: ParameterMap): Promise<APIResponse>;
50
}
51
```
52
53
**Attachments Operations Example:**
54
55
```javascript
56
const { AttachmentsOperations } = require("@zohocrm/nodejs-sdk-2.0/core/com/zoho/crm/api/attachments/attachments_operations");
57
const { FileBodyWrapper } = require("@zohocrm/nodejs-sdk-2.0/core/com/zoho/crm/api/attachments/file_body_wrapper");
58
const fs = require("fs");
59
60
const attachmentsOp = new AttachmentsOperations();
61
62
// Get all attachments for a record
63
const attachmentsResponse = await attachmentsOp.getAttachments("Leads", "record_id_here");
64
65
if (attachmentsResponse != null) {
66
const responseObject = attachmentsResponse.object;
67
if (responseObject instanceof ResponseWrapper) {
68
const attachments = responseObject.getData();
69
attachments.forEach(attachment => {
70
console.log(`Attachment: ${attachment.getFileName()}, Size: ${attachment.getSize()}`);
71
});
72
}
73
}
74
75
// Upload a file attachment
76
const fileStream = fs.createReadStream("path/to/document.pdf");
77
const fileWrapper = new FileBodyWrapper();
78
fileWrapper.setFile(fileStream);
79
80
const uploadResponse = await attachmentsOp.uploadAttachment("Leads", "record_id_here", fileWrapper);
81
82
if (uploadResponse != null) {
83
const responseObject = uploadResponse.object;
84
if (responseObject instanceof ActionWrapper) {
85
const actionResponses = responseObject.getData();
86
actionResponses.forEach(actionResponse => {
87
if (actionResponse instanceof SuccessResponse) {
88
console.log("File uploaded successfully: " + actionResponse.getMessage());
89
}
90
});
91
}
92
}
93
94
// Download an attachment
95
const downloadResponse = await attachmentsOp.downloadAttachment("Leads", "record_id_here", "attachment_id_here");
96
97
if (downloadResponse != null) {
98
const responseObject = downloadResponse.object;
99
if (responseObject instanceof FileBodyWrapper) {
100
const fileStream = responseObject.getFile();
101
// Save the file stream to local file system
102
const writeStream = fs.createWriteStream("downloaded_file.pdf");
103
fileStream.pipe(writeStream);
104
}
105
}
106
107
// Delete an attachment
108
const deleteResponse = await attachmentsOp.deleteAttachment("Leads", "record_id_here", "attachment_id_here");
109
```
110
111
### File Operations
112
113
General file upload operations for temporary file storage.
114
115
```javascript { .api }
116
/**
117
* Operations for general file management and temporary uploads
118
*/
119
class FileOperations {
120
/**
121
* Upload a file to temporary storage (e.g., for bulk operations)
122
* @param request - File body wrapper containing the file to upload
123
* @returns Promise with APIResponse containing file upload results
124
*/
125
uploadFile(request: FileBodyWrapper): Promise<APIResponse>;
126
}
127
```
128
129
**File Operations Example:**
130
131
```javascript
132
const { FileOperations } = require("@zohocrm/nodejs-sdk-2.0/core/com/zoho/crm/api/file/file_operations");
133
const { FileBodyWrapper } = require("@zohocrm/nodejs-sdk-2.0/core/com/zoho/crm/api/file/file_body_wrapper");
134
const fs = require("fs");
135
136
const fileOperations = new FileOperations();
137
138
// Upload file for temporary storage
139
const csvStream = fs.createReadStream("bulk_import_data.csv");
140
const fileWrapper = new FileBodyWrapper();
141
fileWrapper.setFile(csvStream);
142
143
const uploadResponse = await fileOperations.uploadFile(fileWrapper);
144
145
if (uploadResponse != null) {
146
const responseObject = uploadResponse.object;
147
if (responseObject instanceof ActionWrapper) {
148
const actionResponses = responseObject.getData();
149
actionResponses.forEach(actionResponse => {
150
if (actionResponse instanceof SuccessResponse) {
151
const fileId = actionResponse.getDetails().get("file_id");
152
console.log("Temporary file uploaded with ID: " + fileId);
153
// Use this file_id for bulk operations
154
}
155
});
156
}
157
}
158
```
159
160
### Attachment Data Model
161
162
Core data structures for attachment management.
163
164
```javascript { .api }
165
/**
166
* Represents a file attachment with all metadata
167
*/
168
class Attachment {
169
/** Get attachment ID */
170
getId(): string;
171
/** Set attachment ID */
172
setId(id: string): void;
173
174
/** Get attachment file name */
175
getFileName(): string;
176
/** Set attachment file name */
177
setFileName(fileName: string): void;
178
179
/** Get file size in bytes */
180
getSize(): number;
181
/** Set file size in bytes */
182
setSize(size: number): void;
183
184
/** Get file type/MIME type */
185
getType(): string;
186
/** Set file type/MIME type */
187
setType(type: string): void;
188
189
/** Get attachment description */
190
getDescription(): string;
191
/** Set attachment description */
192
setDescription(description: string): void;
193
194
/** Get attachment creation time */
195
getCreatedTime(): Date;
196
/** Get attachment modification time */
197
getModifiedTime(): Date;
198
199
/** Get user who uploaded the attachment */
200
getCreatedBy(): User;
201
/** Get user who last modified the attachment */
202
getModifiedBy(): User;
203
204
/** Get file owner */
205
getOwner(): User;
206
/** Set file owner */
207
setOwner(owner: User): void;
208
209
/** Get parent record ID */
210
getParentId(): Record;
211
/** Set parent record ID */
212
setParentId(parentId: Record): void;
213
214
/** Check if attachment is editable */
215
getEditable(): boolean;
216
/** Set editable flag */
217
setEditable(editable: boolean): void;
218
219
/** Check if attachment is sharable */
220
getSharable(): boolean;
221
/** Set sharable flag */
222
setSharable(sharable: boolean): void;
223
224
/** Get file link URL */
225
getFileId(): string;
226
/** Set file link URL */
227
setFileId(fileId: string): void;
228
229
/** Get attachment link URL */
230
getLinkUrl(): string;
231
/** Set attachment link URL */
232
setLinkUrl(linkUrl: string): void;
233
}
234
235
/**
236
* File body wrapper for file uploads and downloads
237
*/
238
class FileBodyWrapper {
239
/** Get file stream */
240
getFile(): any;
241
/** Set file stream for upload */
242
setFile(file: any): void;
243
}
244
245
/**
246
* Response wrapper for attachment GET operations
247
*/
248
class ResponseWrapper {
249
/** Get attachments data */
250
getData(): Attachment[];
251
/** Get pagination info */
252
getInfo(): Info;
253
}
254
255
/**
256
* Action wrapper for attachment POST/PUT/DELETE operations
257
*/
258
class ActionWrapper {
259
/** Get action results */
260
getData(): ActionResponse[];
261
}
262
```
263
264
### Query Parameters for Attachments
265
266
Parameters for customizing attachment operations.
267
268
```javascript { .api }
269
/**
270
* Parameters for getAttachments operation
271
*/
272
class GetAttachmentsParam {
273
static FIELDS: Param; // Fields to retrieve
274
static IDS: Param; // Specific attachment IDs
275
static PAGE: Param; // Page number for pagination
276
static PER_PAGE: Param; // Attachments per page
277
}
278
```
279
280
**Parameter Usage Example:**
281
282
```javascript
283
const { ParameterMap } = require("@zohocrm/nodejs-sdk-2.0/routes/parameter_map");
284
const { GetAttachmentsParam } = require("@zohocrm/nodejs-sdk-2.0/core/com/zoho/crm/api/attachments/attachments_operations");
285
286
// Setup parameters for getting attachments
287
const paramMap = new ParameterMap();
288
await paramMap.add(GetAttachmentsParam.FIELDS, "file_name,size,created_time,created_by");
289
await paramMap.add(GetAttachmentsParam.PAGE, 1);
290
await paramMap.add(GetAttachmentsParam.PER_PAGE, 200);
291
292
// Get attachments with specific fields
293
const response = await attachmentsOp.getAttachments("Leads", "record_id_here", paramMap);
294
```
295
296
### File Upload Utilities
297
298
Utility functions and helpers for file operations.
299
300
```javascript { .api }
301
/**
302
* File upload configuration and utilities
303
*/
304
class FileUploadConfig {
305
/** Maximum file size in bytes (default: 20MB) */
306
static MAX_FILE_SIZE: number = 20971520;
307
308
/** Supported file types for attachments */
309
static SUPPORTED_TYPES: string[] = [
310
"application/pdf",
311
"application/msword",
312
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
313
"application/vnd.ms-excel",
314
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
315
"application/vnd.ms-powerpoint",
316
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
317
"text/plain",
318
"text/csv",
319
"image/jpeg",
320
"image/jpg",
321
"image/png",
322
"image/gif",
323
"image/bmp",
324
"image/tiff"
325
];
326
327
/** Image file types */
328
static IMAGE_TYPES: string[] = [
329
"image/jpeg",
330
"image/jpg",
331
"image/png",
332
"image/gif",
333
"image/bmp",
334
"image/tiff"
335
];
336
337
/** Document file types */
338
static DOCUMENT_TYPES: string[] = [
339
"application/pdf",
340
"application/msword",
341
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
342
"text/plain",
343
"text/rtf"
344
];
345
346
/** Spreadsheet file types */
347
static SPREADSHEET_TYPES: string[] = [
348
"application/vnd.ms-excel",
349
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
350
"text/csv"
351
];
352
}
353
354
/**
355
* File helper utilities
356
*/
357
class FileHelpers {
358
/**
359
* Check if file type is supported
360
* @param mimeType - MIME type of the file
361
* @returns boolean indicating if file type is supported
362
*/
363
static isSupportedType(mimeType: string): boolean {
364
return FileUploadConfig.SUPPORTED_TYPES.includes(mimeType);
365
}
366
367
/**
368
* Check if file is an image
369
* @param mimeType - MIME type of the file
370
* @returns boolean indicating if file is an image
371
*/
372
static isImage(mimeType: string): boolean {
373
return FileUploadConfig.IMAGE_TYPES.includes(mimeType);
374
}
375
376
/**
377
* Check if file size is within limits
378
* @param fileSize - Size of file in bytes
379
* @returns boolean indicating if size is acceptable
380
*/
381
static isValidSize(fileSize: number): boolean {
382
return fileSize <= FileUploadConfig.MAX_FILE_SIZE;
383
}
384
385
/**
386
* Get file extension from filename
387
* @param fileName - Name of the file
388
* @returns File extension or empty string
389
*/
390
static getFileExtension(fileName: string): string {
391
const lastDot = fileName.lastIndexOf('.');
392
return lastDot > 0 ? fileName.substring(lastDot + 1).toLowerCase() : '';
393
}
394
395
/**
396
* Format file size for display
397
* @param bytes - File size in bytes
398
* @returns Formatted size string
399
*/
400
static formatFileSize(bytes: number): string {
401
if (bytes === 0) return '0 Bytes';
402
403
const k = 1024;
404
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
405
const i = Math.floor(Math.log(bytes) / Math.log(k));
406
407
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
408
}
409
}
410
```
411
412
**File Upload Best Practices Example:**
413
414
```javascript
415
const fs = require("fs");
416
const path = require("path");
417
418
async function uploadFileWithValidation(filePath, moduleAPIName, recordId) {
419
const attachmentsOp = new AttachmentsOperations();
420
421
try {
422
// Check if file exists
423
if (!fs.existsSync(filePath)) {
424
throw new Error("File does not exist: " + filePath);
425
}
426
427
// Get file stats
428
const stats = fs.statSync(filePath);
429
const fileName = path.basename(filePath);
430
const fileExtension = FileHelpers.getFileExtension(fileName);
431
432
// Validate file size
433
if (!FileHelpers.isValidSize(stats.size)) {
434
throw new Error(`File size ${FileHelpers.formatFileSize(stats.size)} exceeds maximum allowed size of ${FileHelpers.formatFileSize(FileUploadConfig.MAX_FILE_SIZE)}`);
435
}
436
437
// Create file stream
438
const fileStream = fs.createReadStream(filePath);
439
const fileWrapper = new FileBodyWrapper();
440
fileWrapper.setFile(fileStream);
441
442
// Upload file
443
const uploadResponse = await attachmentsOp.uploadAttachment(moduleAPIName, recordId, fileWrapper);
444
445
if (uploadResponse != null) {
446
const responseObject = uploadResponse.object;
447
if (responseObject instanceof ActionWrapper) {
448
const actionResponses = responseObject.getData();
449
for (const actionResponse of actionResponses) {
450
if (actionResponse instanceof SuccessResponse) {
451
console.log("File uploaded successfully:", fileName);
452
return actionResponse.getDetails();
453
} else if (actionResponse instanceof APIException) {
454
console.error("Upload failed:", actionResponse.getMessage());
455
throw new Error(actionResponse.getMessage());
456
}
457
}
458
}
459
}
460
} catch (error) {
461
console.error("Error uploading file:", error.message);
462
throw error;
463
}
464
}
465
466
// Usage example
467
async function uploadDocument() {
468
try {
469
const result = await uploadFileWithValidation(
470
"/path/to/document.pdf",
471
"Leads",
472
"123456789012345678"
473
);
474
console.log("Upload result:", result);
475
} catch (error) {
476
console.error("Upload failed:", error.message);
477
}
478
}
479
```