0
# Attachment Operations
1
2
File attachment management with support for binary data, proper content types, and efficient streaming for documents stored in remote CouchDB databases.
3
4
## Capabilities
5
6
### Attachment Retrieval
7
8
Retrieves a document attachment by its ID and returns the binary data.
9
10
```javascript { .api }
11
/**
12
* Get a document attachment by ID
13
* @param docId - Document ID containing the attachment
14
* @param attachmentId - Attachment ID within the document
15
* @param opts - Retrieval options including revision
16
* @param callback - Callback function receiving attachment data
17
*/
18
api.getAttachment(docId, attachmentId, opts, callback): void;
19
```
20
21
**Usage Examples:**
22
23
```javascript
24
// Get attachment from latest document revision
25
db.getAttachment('user:john', 'profile-photo.jpg', (err, blob) => {
26
if (err) {
27
console.error('Attachment not found:', err);
28
return;
29
}
30
31
console.log('Attachment size:', blob.size);
32
console.log('Content type:', blob.type);
33
34
// In browser - create download link
35
if (typeof window !== 'undefined') {
36
const url = URL.createObjectURL(blob);
37
const link = document.createElement('a');
38
link.href = url;
39
link.download = 'profile-photo.jpg';
40
link.click();
41
}
42
43
// In Node.js - save to file
44
if (typeof process !== 'undefined' && !process.browser) {
45
const fs = require('fs');
46
fs.writeFileSync('downloaded-photo.jpg', blob);
47
}
48
});
49
50
// Get attachment from specific revision
51
db.getAttachment('user:john', 'profile-photo.jpg', {
52
rev: '2-abc123'
53
}, (err, blob) => {
54
if (err) {
55
console.error('Attachment not found in revision:', err);
56
return;
57
}
58
59
console.log('Retrieved attachment from specific revision');
60
});
61
```
62
63
### Attachment Creation/Update
64
65
Adds a new attachment to a document or updates an existing attachment.
66
67
```javascript { .api }
68
/**
69
* Add or update a document attachment
70
* @param docId - Document ID to attach to
71
* @param attachmentId - Attachment ID within the document
72
* @param rev - Document revision (optional for new attachments)
73
* @param blob - Attachment data (Blob, Buffer, or base64 string)
74
* @param type - MIME content type
75
* @param callback - Callback function receiving save result
76
*/
77
api.putAttachment(docId, attachmentId, rev, blob, type, callback): void;
78
```
79
80
**Usage Examples:**
81
82
```javascript
83
// Add attachment to existing document
84
db.get('user:john', (err, doc) => {
85
if (err) {
86
console.error('Document not found:', err);
87
return;
88
}
89
90
// In browser - from file input
91
const fileInput = document.getElementById('photoInput');
92
const file = fileInput.files[0];
93
94
db.putAttachment('user:john', 'profile-photo.jpg', doc._rev, file, file.type, (err, result) => {
95
if (err) {
96
console.error('Attachment upload failed:', err);
97
return;
98
}
99
100
console.log('Attachment saved, new revision:', result.rev);
101
});
102
});
103
104
// Add attachment from base64 string
105
const base64Image = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==';
106
107
db.get('user:jane', (err, doc) => {
108
if (err) {
109
console.error('Document not found:', err);
110
return;
111
}
112
113
db.putAttachment('user:jane', 'avatar.png', doc._rev, base64Image, 'image/png', (err, result) => {
114
if (err) {
115
console.error('Attachment upload failed:', err);
116
return;
117
}
118
119
console.log('Base64 attachment saved:', result.rev);
120
});
121
});
122
123
// Add attachment to new document (without revision)
124
const textData = new Blob(['Hello, world!'], { type: 'text/plain' });
125
126
db.putAttachment('note:greeting', 'content.txt', textData, 'text/plain', (err, result) => {
127
if (err) {
128
console.error('Attachment upload failed:', err);
129
return;
130
}
131
132
console.log('Attachment saved to new document:', result.rev);
133
});
134
```
135
136
### Attachment Deletion
137
138
Removes an attachment from a document.
139
140
```javascript { .api }
141
/**
142
* Remove an attachment from a document
143
* @param docId - Document ID containing the attachment
144
* @param attachmentId - Attachment ID to remove
145
* @param rev - Current document revision
146
* @param callback - Callback function receiving deletion result
147
*/
148
api.removeAttachment(docId, attachmentId, rev, callback): void;
149
```
150
151
**Usage Examples:**
152
153
```javascript
154
// Remove attachment
155
db.get('user:john', (err, doc) => {
156
if (err) {
157
console.error('Document not found:', err);
158
return;
159
}
160
161
// Check if attachment exists
162
if (!doc._attachments || !doc._attachments['profile-photo.jpg']) {
163
console.log('Attachment not found in document');
164
return;
165
}
166
167
db.removeAttachment('user:john', 'profile-photo.jpg', doc._rev, (err, result) => {
168
if (err) {
169
console.error('Attachment removal failed:', err);
170
return;
171
}
172
173
console.log('Attachment removed, new revision:', result.rev);
174
});
175
});
176
177
// Remove multiple attachments
178
db.get('document:with-attachments', (err, doc) => {
179
if (err) {
180
console.error('Document not found:', err);
181
return;
182
}
183
184
const attachmentIds = Object.keys(doc._attachments || {});
185
186
// Remove attachments sequentially
187
let currentRev = doc._rev;
188
189
const removeNext = (index) => {
190
if (index >= attachmentIds.length) {
191
console.log('All attachments removed');
192
return;
193
}
194
195
db.removeAttachment(doc._id, attachmentIds[index], currentRev, (err, result) => {
196
if (err) {
197
console.error(`Failed to remove ${attachmentIds[index]}:`, err);
198
return;
199
}
200
201
currentRev = result.rev;
202
console.log(`Removed ${attachmentIds[index]}`);
203
removeNext(index + 1);
204
});
205
};
206
207
removeNext(0);
208
});
209
```
210
211
## Working with Different Data Types
212
213
### Browser File Handling
214
215
```javascript
216
// Handle file input in browsers
217
function handleFileUpload(event) {
218
const file = event.target.files[0];
219
if (!file) return;
220
221
const docId = 'upload:' + Date.now();
222
223
db.putAttachment(docId, file.name, file, file.type, (err, result) => {
224
if (err) {
225
console.error('Upload failed:', err);
226
return;
227
}
228
229
console.log('File uploaded successfully:', result.rev);
230
});
231
}
232
233
// Create download link for attachment
234
function downloadAttachment(docId, attachmentId) {
235
db.getAttachment(docId, attachmentId, (err, blob) => {
236
if (err) {
237
console.error('Download failed:', err);
238
return;
239
}
240
241
const url = URL.createObjectURL(blob);
242
const link = document.createElement('a');
243
link.href = url;
244
link.download = attachmentId;
245
document.body.appendChild(link);
246
link.click();
247
document.body.removeChild(link);
248
URL.revokeObjectURL(url);
249
});
250
}
251
```
252
253
### Node.js File Handling
254
255
```javascript
256
const fs = require('fs');
257
const path = require('path');
258
259
// Upload file from filesystem
260
function uploadFile(filePath, docId) {
261
const fileName = path.basename(filePath);
262
const fileBuffer = fs.readFileSync(filePath);
263
264
// Determine content type based on extension
265
const ext = path.extname(fileName).toLowerCase();
266
const contentType = {
267
'.jpg': 'image/jpeg',
268
'.jpeg': 'image/jpeg',
269
'.png': 'image/png',
270
'.pdf': 'application/pdf',
271
'.txt': 'text/plain'
272
}[ext] || 'application/octet-stream';
273
274
db.putAttachment(docId, fileName, fileBuffer, contentType, (err, result) => {
275
if (err) {
276
console.error('File upload failed:', err);
277
return;
278
}
279
280
console.log('File uploaded:', result.rev);
281
});
282
}
283
284
// Save attachment to filesystem
285
function saveAttachment(docId, attachmentId, outputPath) {
286
db.getAttachment(docId, attachmentId, (err, buffer) => {
287
if (err) {
288
console.error('Download failed:', err);
289
return;
290
}
291
292
fs.writeFileSync(outputPath, buffer);
293
console.log('Attachment saved to:', outputPath);
294
});
295
}
296
```
297
298
## Types
299
300
```javascript { .api }
301
// Attachment data types
302
type AttachmentData = Blob | Buffer | string;
303
304
// Get attachment options
305
interface GetAttachmentOptions {
306
rev?: string;
307
}
308
309
// Attachment info in document
310
interface AttachmentInfo {
311
content_type: string;
312
revpos: number;
313
digest: string;
314
length: number;
315
stub: boolean;
316
data?: string; // base64 data when fetched
317
}
318
319
// Document with attachments
320
interface DocumentWithAttachments extends PouchDoc {
321
_attachments?: {
322
[attachmentId: string]: AttachmentInfo;
323
};
324
}
325
326
// Attachment operation result
327
interface AttachmentResult {
328
ok: boolean;
329
id: string;
330
rev: string;
331
}
332
333
// Content type constants
334
type ContentType =
335
| 'image/jpeg'
336
| 'image/png'
337
| 'image/gif'
338
| 'image/webp'
339
| 'application/pdf'
340
| 'text/plain'
341
| 'text/html'
342
| 'application/json'
343
| 'application/octet-stream'
344
| string;
345
```