0
# Cloud Storage Integration
1
2
Direct upload integration with Amazon S3, Google Cloud Storage, and other S3-compatible services for seamless cloud storage of processed images.
3
4
## Capabilities
5
6
### Store to Cloud Storage
7
8
Upload processed images directly to cloud storage services without downloading them locally first.
9
10
```typescript { .api }
11
/**
12
* Store processed image to cloud storage
13
* @param options - Cloud storage configuration
14
* @returns ResultMeta instance for accessing storage metadata
15
*/
16
store(options: StoreOptions): ResultMeta;
17
18
interface StoreOptions {
19
/** Storage service type */
20
service: "s3" | "gcs";
21
/** AWS access key ID (required for S3) */
22
aws_access_key_id?: string;
23
/** AWS secret access key (required for S3) */
24
aws_secret_access_key?: string;
25
/** AWS region (optional, defaults to us-east-1) */
26
region?: string;
27
/** Storage path including bucket/container and object key */
28
path: string;
29
/** Additional service-specific headers and options */
30
[key: string]: any;
31
}
32
```
33
34
### Amazon S3 Storage
35
36
Store images directly to Amazon S3 buckets with full authentication and region support.
37
38
**Usage Examples:**
39
40
```typescript
41
const tinify = require("tinify");
42
43
tinify.key = "your-api-key";
44
45
// Basic S3 storage
46
const resultMeta = tinify.fromFile("large-image.jpg")
47
.resize({ method: "fit", width: 1200 })
48
.store({
49
service: "s3",
50
aws_access_key_id: "AKIAIOSFODNN7EXAMPLE",
51
aws_secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
52
region: "us-west-2",
53
path: "my-images-bucket/processed/optimized-image.jpg"
54
});
55
56
// Get storage location
57
const location = await resultMeta.location();
58
console.log(`Image stored at: ${location}`);
59
60
// With additional S3 headers
61
const resultMeta2 = tinify.fromFile("photo.png")
62
.convert({ type: "image/webp" })
63
.store({
64
service: "s3",
65
aws_access_key_id: "ACCESS_KEY",
66
aws_secret_access_key: "SECRET_KEY",
67
region: "eu-west-1",
68
path: "photos-bucket/webp/photo.webp",
69
// Additional S3-specific headers
70
"x-amz-acl": "public-read",
71
"x-amz-meta-title": "Optimized Photo",
72
"cache-control": "max-age=31536000"
73
});
74
75
// Complex transformation with S3 storage
76
const transformedResult = tinify.fromUrl("https://example.com/original.png")
77
.resize({ method: "cover", width: 800, height: 600 })
78
.preserve("copyright")
79
.convert({ type: "image/webp" })
80
.store({
81
service: "s3",
82
aws_access_key_id: "ACCESS_KEY",
83
aws_secret_access_key: "SECRET_KEY",
84
region: "us-east-1",
85
path: "processed-images/thumbnails/image-800x600.webp"
86
});
87
88
const dimensions = {
89
width: await transformedResult.width(),
90
height: await transformedResult.height()
91
};
92
```
93
94
### Google Cloud Storage
95
96
Store images to Google Cloud Storage buckets.
97
98
**Usage Examples:**
99
100
```typescript
101
const tinify = require("tinify");
102
103
tinify.key = "your-api-key";
104
105
// Google Cloud Storage
106
const resultMeta = tinify.fromFile("image.jpg")
107
.resize({ method: "fit", width: 1000 })
108
.store({
109
service: "gcs",
110
// GCS authentication and configuration
111
path: "my-gcs-bucket/images/processed-image.jpg"
112
// Additional GCS-specific options as needed
113
});
114
115
const location = await resultMeta.location();
116
const dimensions = {
117
width: await resultMeta.width(),
118
height: await resultMeta.height()
119
};
120
```
121
122
### S3-Compatible Services
123
124
The S3 service option works with other S3-compatible storage services by specifying custom endpoints and regions.
125
126
**Usage Example:**
127
128
```typescript
129
const tinify = require("tinify");
130
131
tinify.key = "your-api-key";
132
133
// Custom S3-compatible service (e.g., DigitalOcean Spaces, MinIO)
134
const resultMeta = tinify.fromFile("document.png")
135
.resize({ method: "fit", width: 800 })
136
.store({
137
service: "s3",
138
aws_access_key_id: "CUSTOM_ACCESS_KEY",
139
aws_secret_access_key: "CUSTOM_SECRET_KEY",
140
region: "custom-region",
141
path: "my-space/documents/processed-document.png",
142
// Custom endpoint for S3-compatible services
143
"x-amz-endpoint": "https://custom-endpoint.example.com"
144
});
145
```
146
147
### Storage Metadata
148
149
Access metadata about stored images including dimensions and storage location.
150
151
```typescript { .api }
152
class ResultMeta {
153
/** Get stored image width in pixels */
154
width(): Promise<number>;
155
width(callback: (err: Error | null, width?: number) => void): void;
156
157
/** Get stored image height in pixels */
158
height(): Promise<number>;
159
height(callback: (err: Error | null, height?: number) => void): void;
160
161
/** Get storage location URL */
162
location(): Promise<string>;
163
location(callback: (err: Error | null, location?: string) => void): void;
164
}
165
```
166
167
**Usage Example:**
168
169
```typescript
170
const tinify = require("tinify");
171
172
tinify.key = "your-api-key";
173
174
const resultMeta = tinify.fromFile("photo.jpg")
175
.resize({ method: "cover", width: 500, height: 500 })
176
.store({
177
service: "s3",
178
aws_access_key_id: "ACCESS_KEY",
179
aws_secret_access_key: "SECRET_KEY",
180
region: "us-west-1",
181
path: "thumbnails/profile-photo.jpg"
182
});
183
184
// Promise-based metadata access
185
const metadata = {
186
width: await resultMeta.width(),
187
height: await resultMeta.height(),
188
location: await resultMeta.location()
189
};
190
191
console.log(`Stored image: ${metadata.width}×${metadata.height} at ${metadata.location}`);
192
193
// Callback-based metadata access
194
resultMeta.location((err, location) => {
195
if (err) {
196
console.error("Failed to get location:", err.message);
197
} else {
198
console.log(`Image available at: ${location}`);
199
}
200
});
201
```
202
203
### Batch Storage Operations
204
205
Store multiple processed variations of the same image to different storage locations.
206
207
**Usage Example:**
208
209
```typescript
210
const tinify = require("tinify");
211
212
tinify.key = "your-api-key";
213
214
const baseSource = tinify.fromFile("high-res-photo.jpg");
215
216
// Store multiple sizes
217
const thumbnailMeta = baseSource
218
.resize({ method: "cover", width: 200, height: 200 })
219
.store({
220
service: "s3",
221
aws_access_key_id: "ACCESS_KEY",
222
aws_secret_access_key: "SECRET_KEY",
223
region: "us-west-2",
224
path: "images/thumbnails/photo-200x200.jpg"
225
});
226
227
const mediumMeta = baseSource
228
.resize({ method: "fit", width: 800 })
229
.store({
230
service: "s3",
231
aws_access_key_id: "ACCESS_KEY",
232
aws_secret_access_key: "SECRET_KEY",
233
region: "us-west-2",
234
path: "images/medium/photo-800w.jpg"
235
});
236
237
const webpMeta = baseSource
238
.resize({ method: "fit", width: 1200 })
239
.convert({ type: "image/webp" })
240
.store({
241
service: "s3",
242
aws_access_key_id: "ACCESS_KEY",
243
aws_secret_access_key: "SECRET_KEY",
244
region: "us-west-2",
245
path: "images/webp/photo-1200w.webp"
246
});
247
248
// Get all storage locations
249
const locations = {
250
thumbnail: await thumbnailMeta.location(),
251
medium: await mediumMeta.location(),
252
webp: await webpMeta.location()
253
};
254
255
console.log("All variations stored:", locations);
256
```
257
258
## Error Handling
259
260
Cloud storage operations can throw the following errors:
261
262
- **ClientError**: Invalid storage configuration, authentication failure, or permission issues
263
- **AccountError**: Tinify API key issues or monthly limit exceeded
264
- **ConnectionError**: Network connectivity problems
265
- **ServerError**: Temporary issues with storage services or Tinify API
266
267
**Error Handling Example:**
268
269
```typescript
270
const tinify = require("tinify");
271
272
tinify.key = "your-api-key";
273
274
try {
275
const resultMeta = tinify.fromFile("image.jpg")
276
.resize({ method: "fit", width: 1000 })
277
.store({
278
service: "s3",
279
aws_access_key_id: "ACCESS_KEY",
280
aws_secret_access_key: "SECRET_KEY",
281
region: "us-west-1",
282
path: "my-bucket/processed/image.jpg"
283
});
284
285
const location = await resultMeta.location();
286
console.log(`Successfully stored at: ${location}`);
287
288
} catch (error) {
289
if (error instanceof tinify.ClientError) {
290
if (error.status === 403) {
291
console.error("S3 permission denied:", error.message);
292
} else if (error.status === 400) {
293
console.error("Invalid S3 configuration:", error.message);
294
} else {
295
console.error("Storage error:", error.message);
296
}
297
} else if (error instanceof tinify.AccountError) {
298
console.error("Tinify account issue:", error.message);
299
} else if (error instanceof tinify.ConnectionError) {
300
console.error("Network error:", error.message);
301
}
302
}
303
```