or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

attachments-files.mdauthentication.mdbulk-operations.mdfields-metadata.mdindex.mdinitialization.mdorganization-settings.mdrecords.mdrelated-records.mdtags-organization.mdusers.md

attachments-files.mddocs/

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

```