0
# Core Operations
1
2
OpenDAL provides a comprehensive set of file and directory operations through both async (`Operator`) and blocking (`BlockingOperator`) interfaces. All operations follow consistent patterns and provide the same functionality across all storage backends.
3
4
```rust
5
use std::future::Future;
6
use std::ops::RangeBounds;
7
use std::pin::Pin;
8
use std::task::{Context, Poll};
9
use futures::Stream;
10
```
11
12
## Capabilities
13
14
### File Reading Operations
15
16
Read file content and metadata from storage backends.
17
18
```rust { .api }
19
impl Operator {
20
/// Read the entire content of a file
21
pub fn read(&self, path: &str) -> impl Future<Output = Result<Buffer>>;
22
23
/// Read file with advanced options (range, conditions)
24
pub fn read_with(&self, path: &str) -> FutureRead<impl Future<Output = Result<Buffer>>>;
25
26
/// Create a streaming reader for large files
27
pub fn reader(&self, path: &str) -> impl Future<Output = Result<Reader>>;
28
29
/// Create a streaming reader with options
30
pub fn reader_with(&self, path: &str) -> FutureReader<impl Future<Output = Result<Reader>>>;
31
32
/// Get file metadata without reading content
33
pub fn stat(&self, path: &str) -> impl Future<Output = Result<Metadata>>;
34
35
/// Get metadata with advanced options
36
pub fn stat_with(&self, path: &str) -> FutureStat<impl Future<Output = Result<Metadata>>>;
37
}
38
39
/// Future builder for read operations with options
40
pub struct FutureRead<F>;
41
impl<F> FutureRead<F> {
42
/// Set byte range to read (e.g., 0..1024)
43
pub fn range(self, range: impl RangeBounds<u64>) -> Self;
44
/// Set conditional read based on ETag match
45
pub fn if_match(self, etag: &str) -> Self;
46
/// Set conditional read based on ETag non-match
47
pub fn if_none_match(self, etag: &str) -> Self;
48
}
49
50
impl<F> Future for FutureRead<F>
51
where
52
F: Future<Output = Result<Buffer>>,
53
{
54
type Output = Result<Buffer>;
55
/// Execute the read operation
56
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
57
}
58
59
/// Async streaming reader for large files
60
pub struct Reader;
61
impl Reader {
62
/// Read the next chunk of data
63
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
64
}
65
```
66
67
**Usage Examples:**
68
69
```rust
70
use opendal::{Operator, services};
71
72
// Read entire file
73
let content = op.read("data.txt").await?;
74
println!("Content: {}", String::from_utf8_lossy(&content));
75
76
// Read with byte range
77
let partial = op.read_with("large-file.dat")
78
.range(0..1024)
79
.await?;
80
81
// Streaming read for large files
82
let mut reader = op.reader("big-file.zip").await?;
83
let mut buffer = vec![0; 8192];
84
while let n = reader.read(&mut buffer).await? {
85
if n == 0 { break; }
86
// Process chunk
87
}
88
89
// Get file metadata
90
let meta = op.stat("document.pdf").await?;
91
println!("Size: {} bytes", meta.content_length());
92
println!("Modified: {:?}", meta.last_modified());
93
```
94
95
### File Writing Operations
96
97
Write data to storage backends with various options.
98
99
```rust { .api }
100
impl Operator {
101
/// Write data to a file, overwriting if exists
102
pub fn write(&self, path: &str, bs: impl Into<Buffer>) -> impl Future<Output = Result<()>>;
103
104
/// Write with advanced options (content type, cache control)
105
pub fn write_with(&self, path: &str, bs: impl Into<Buffer>) -> FutureWrite<impl Future<Output = Result<()>>>;
106
107
/// Create a streaming writer for large files
108
pub fn writer(&self, path: &str) -> impl Future<Output = Result<Writer>>;
109
110
/// Create streaming writer with options
111
pub fn writer_with(&self, path: &str) -> FutureWriter<impl Future<Output = Result<Writer>>>;
112
}
113
114
/// Future builder for write operations with options
115
pub struct FutureWrite;
116
impl FutureWrite {
117
/// Set content MIME type
118
pub fn content_type(mut self, content_type: &str) -> Self;
119
/// Set content disposition header
120
pub fn content_disposition(mut self, disposition: &str) -> Self;
121
/// Set cache control header
122
pub fn cache_control(mut self, cache_control: &str) -> Self;
123
/// Execute the write operation
124
pub async fn await(self) -> Result<()>;
125
}
126
127
/// Async streaming writer for large files
128
pub struct Writer;
129
impl Writer {
130
/// Write a chunk of data
131
pub async fn write(&mut self, bs: impl Into<Buffer>) -> Result<()>;
132
/// Finalize and close the writer
133
pub async fn close(self) -> Result<()>;
134
}
135
```
136
137
**Usage Examples:**
138
139
```rust
140
// Simple write
141
op.write("output.txt", "Hello, World!").await?;
142
143
// Write with content type
144
op.write_with("image.jpg", image_bytes)
145
.content_type("image/jpeg")
146
.cache_control("max-age=3600")
147
.await?;
148
149
// Streaming write for large files
150
let mut writer = op.writer("upload.bin").await?;
151
for chunk in large_data_chunks {
152
writer.write(chunk).await?;
153
}
154
writer.close().await?;
155
```
156
157
### Directory Operations
158
159
List and manage directory contents.
160
161
```rust { .api }
162
impl Operator {
163
/// List directory contents as a vector
164
pub fn list(&self, path: &str) -> impl Future<Output = Result<Vec<Entry>>>;
165
166
/// List directory with advanced options
167
pub fn list_with(&self, path: &str) -> FutureList;
168
169
/// Create streaming lister for large directories
170
pub fn lister(&self, path: &str) -> impl Future<Output = Result<Lister>>;
171
172
/// Create streaming lister with options
173
pub fn lister_with(&self, path: &str) -> FutureLister;
174
175
/// Create a directory
176
pub fn create_dir(&self, path: &str) -> impl Future<Output = Result<()>>;
177
}
178
179
/// Directory entry with metadata
180
pub struct Entry {
181
pub fn path(&self) -> &str;
182
pub fn metadata(&self) -> &Metadata;
183
pub fn mode(&self) -> EntryMode;
184
}
185
186
/// Entry type enumeration
187
pub enum EntryMode {
188
FILE,
189
DIR,
190
Unknown,
191
}
192
193
/// Future builder for list operations
194
pub struct FutureList;
195
impl FutureList {
196
/// List recursively through subdirectories
197
pub fn recursive(mut self, recursive: bool) -> Self;
198
/// Start listing after a specific path
199
pub fn start_after(mut self, path: &str) -> Self;
200
/// Specify which metadata to fetch
201
pub fn metakey(mut self, metakey: Metakey) -> Self;
202
}
203
204
/// Async streaming lister for large directories
205
pub struct Lister;
206
impl Lister {
207
/// Get the next entry
208
pub async fn next(&mut self) -> Result<Option<Entry>>;
209
}
210
```
211
212
**Usage Examples:**
213
214
```rust
215
// List directory contents
216
let entries = op.list("/photos/").await?;
217
for entry in entries {
218
println!("{}: {} bytes", entry.path(), entry.metadata().content_length());
219
}
220
221
// Recursive listing
222
let all_files = op.list_with("/documents/")
223
.recursive(true)
224
.await?;
225
226
// Streaming lister for large directories
227
let mut lister = op.lister("/logs/").await?;
228
while let Some(entry) = lister.next().await? {
229
if entry.mode() == EntryMode::FILE {
230
println!("File: {}", entry.path());
231
}
232
}
233
234
// Create directory
235
op.create_dir("/new-folder/").await?;
236
```
237
238
### File Management Operations
239
240
Copy, move, and delete files.
241
242
```rust { .api }
243
impl Operator {
244
/// Copy a file from source to destination
245
pub fn copy(&self, from: &str, to: &str) -> impl Future<Output = Result<()>>;
246
247
/// Rename/move a file from source to destination
248
pub fn rename(&self, from: &str, to: &str) -> impl Future<Output = Result<()>>;
249
250
/// Delete a single file
251
pub fn delete(&self, path: &str) -> impl Future<Output = Result<()>>;
252
}
253
```
254
255
**Usage Examples:**
256
257
```rust
258
// Copy file
259
op.copy("original.txt", "backup.txt").await?;
260
261
// Move/rename file
262
op.rename("old-name.doc", "new-name.doc").await?;
263
264
// Delete file
265
op.delete("temp-file.tmp").await?;
266
```
267
268
### Batch Operations
269
270
Efficient operations on multiple files.
271
272
```rust { .api }
273
impl Operator {
274
/// Delete multiple files in a single operation
275
pub fn remove(&self, paths: Vec<String>) -> impl Future<Output = Result<()>>;
276
277
/// Delete files from a stream (for very large lists)
278
pub fn remove_via(&self, input: impl Stream<Item = String> + Unpin) -> impl Future<Output = Result<()>>;
279
280
/// Recursively delete all files under a path
281
pub fn remove_all(&self, path: &str) -> impl Future<Output = Result<()>>;
282
}
283
```
284
285
**Usage Examples:**
286
287
```rust
288
use futures::stream;
289
290
// Batch delete specific files
291
let files_to_delete = vec![
292
"temp1.txt".to_string(),
293
"temp2.txt".to_string(),
294
"temp3.txt".to_string(),
295
];
296
op.remove(files_to_delete).await?;
297
298
// Stream-based delete for large lists
299
let file_stream = stream::iter(large_file_list);
300
op.remove_via(file_stream).await?;
301
302
// Recursively delete directory and contents
303
op.remove_all("/temp-data/").await?;
304
```
305
306
### Presigned URL Operations
307
308
Generate time-limited URLs for secure direct access.
309
310
```rust { .api }
311
impl Operator {
312
/// Generate presigned URL for reading
313
pub fn presign_read(&self, path: &str, expire: Duration) -> impl Future<Output = Result<PresignedRequest>>;
314
315
/// Generate presigned URL for writing
316
pub fn presign_write(&self, path: &str, expire: Duration) -> impl Future<Output = Result<PresignedRequest>>;
317
318
/// Generate presigned URL for metadata access
319
pub fn presign_stat(&self, path: &str, expire: Duration) -> impl Future<Output = Result<PresignedRequest>>;
320
321
/// Generate presigned URL with options
322
pub fn presign_read_with(&self, path: &str, expire: Duration) -> FuturePresignRead;
323
}
324
325
/// Presigned request details
326
pub struct PresignedRequest {
327
pub fn method(&self) -> &str;
328
pub fn uri(&self) -> &str;
329
pub fn headers(&self) -> &HeaderMap;
330
}
331
```
332
333
**Usage Examples:**
334
335
```rust
336
use std::time::Duration;
337
338
// Generate presigned download URL (valid for 1 hour)
339
let presigned = op.presign_read("private-file.pdf", Duration::from_secs(3600)).await?;
340
println!("Download URL: {}", presigned.uri());
341
342
// Generate presigned upload URL
343
let upload_req = op.presign_write("uploads/new-file.jpg", Duration::from_secs(1800)).await?;
344
// Client can now upload directly using the presigned URL
345
346
// Presigned URL with range
347
let partial_req = op.presign_read_with("large-file.bin", Duration::from_secs(300))
348
.range(0..1024)
349
.await?;
350
```
351
352
### Blocking Operations
353
354
Synchronous versions of all operations for non-async contexts.
355
356
```rust { .api }
357
impl BlockingOperator {
358
pub fn read(&self, path: &str) -> Result<Buffer>;
359
pub fn write(&self, path: &str, bs: impl Into<Buffer>) -> Result<()>;
360
pub fn stat(&self, path: &str) -> Result<Metadata>;
361
pub fn list(&self, path: &str) -> Result<Vec<Entry>>;
362
pub fn delete(&self, path: &str) -> Result<()>;
363
pub fn copy(&self, from: &str, to: &str) -> Result<()>;
364
pub fn rename(&self, from: &str, to: &str) -> Result<()>;
365
}
366
```
367
368
**Usage Examples:**
369
370
```rust
371
use opendal::BlockingOperator;
372
373
// Convert async operator to blocking
374
let blocking_op = op.blocking();
375
376
// Use synchronous operations
377
let content = blocking_op.read("data.txt")?;
378
blocking_op.write("output.txt", "Processed data")?;
379
let entries = blocking_op.list("/directory/")?;
380
```