29 Using Storage SDK

Topics:

29.1 Uploading with JavaScript Storage SDK

Topics:

29.1.1 Uploading a File

The following upload methods are supported in JavaScript SDK:

  • Upload from a file or byte array

  • Update file metadata

  • File size limitation

29.1.1.1 JavaScript SDK Upload Examples

Upload File Data from In Memory to Oracle Backend for Firebase Storage

import { ref, uploadBytes } from "fusabase/storage";

const recipeRef = ref(storage, "recipes/Scott/Cookies/main.jpg");

// Placeholder file using Blob
const File = new Blob(["fake image content"], { type: "image/jpeg" });

await uploadBytes(recipeRef, File);

console.log("Uploaded placeholder file");

const recipeRef = storage.ref("recipes/Scott/Cookies/main.jpg");

// Placeholder file using Blob
const File = new Blob(["fake image content"], { type: "image/jpeg" });

recipeRef.put(File).then(() => {
  console.log("Uploaded placeholder file");
});

Upload File Metadata

import { ref, uploadBytes } from "fusabase/storage";

const recipeRef = ref(storage, "recipes/Scott/Cookies/main.jpg");

const file = new Blob(["fake image content"], { type: "image/jpeg" });

const metadata = {
  contentType: "image/jpeg",
  cacheControl: "public,max-age=3600",
  customMetadata: {
    recipeId: "Cookies",
    owner: "Scott"
  }
};

await uploadBytes(recipeRef, file, metadata);

console.log("Uploaded with metadata");

const recipeRef = storage.ref("recipes/Scott/Cookies/main.jpg");

const file = new Blob(["fake image content"], { type: "image/jpeg" });

const metadata = {
  contentType: "image/jpeg",
  customMetadata: {
    recipeId: "Cookies",
    owner: "Scott"
  }
};

recipeRef.put(file, metadata)
  .then(() => console.log("Uploaded with metadata"));

29.1.2 Managing and Monitoring Uploads

To manage and monitor the upload, the SDK uses pause(), resume(), and cancel() methods.

Monitor Properties

  1. The state_changed event plays a crucial role in monitoring the state of a file upload. It tracks the progress, pause, resume, success, and failure states during an upload task. The state_changed event is used to observe the status of a file upload, and it provides information about the upload's progress through snapshot properties such as bytesTransferred and totalBytes.
  2. The state_changed event is triggered based on these states:
    • running:
      • Description: The upload is actively in progress.
      • Triggering Condition: This state is triggered when the file upload is actively transferring data.
      • Usage: You can use this state to show a progress bar or display other real-time upload information.
    • paused:
      • Description: The upload is temporarily paused.
      • Triggering Condition: This state occurs when the upload is paused due to factors like network connectivity issues or manual pausing (e.g., a user action).
      • Usage: This state is useful to notify the user that the upload is temporarily stopped and may resume later.
    • success:
      • Description: The upload has completed successfully.
      • Triggering Condition: This state occurs when the file is completely uploaded.
      • Usage: You can trigger notifications or update the UI to show that the upload was completed successfully.
    • failed:
      • Description: The upload has failed.
      • Triggering Condition: This state happens if there was an error during the upload process (e.g., a network failure, unauthorized access).
      • Usage: You can use this state to display an error message or prompt the user to retry the upload.
  3. Snapshot Properties
    1. bytesTransferred
    2. totalBytes
    3. state
    4. metadata
    5. task
    6. ref
29.1.2.1 Managing and Monitoring Uploads Examples

Managing and Monitoring an Upload

// File to upload (for demonstration, replace with an actual file)
const file = new Blob(["Hello, world!"], { type: "text/plain" });  // Example file

// Create a reference to Storage location
const storageRef = storage.ref().child('uploads/' + 'example.txt');

// Start the upload task
const uploadTask = storageRef.put(file);

// Monitor the upload progress
uploadTask.on('state_changed',
  (snapshot) => {
    const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log(`Upload is ${progress}% done`);
    console.log(`Bytes Transferred: ${snapshot.bytesTransferred}`);
    console.log(`Total Bytes: ${snapshot.totalBytes}`);
    console.log(`Current Upload State: ${snapshot.state}`);

    // Handle state changes
    if (snapshot.state === 'paused') {
      console.log('Upload paused');
    }
  },
  (error) => {
    // Handle upload errors
    console.error('Upload failed:', error);
  },
  () => {
    // Handle successful upload completion
    console.log('Upload completed successfully!');
  }
);

// Simulate pause after 3 seconds
setTimeout(() => {
  uploadTask.pause();
  console.log('Upload paused after 3 seconds');
}, 3000);

// Simulate resume after 6 seconds
setTimeout(() => {
  uploadTask.resume();
  console.log('Upload resumed after 6 seconds');
}, 6000);

// Simulate cancel after 9 seconds
setTimeout(() => {
  uploadTask.cancel();
  console.log('Upload canceled after 9 seconds');
}, 9000);

29.2 Uploading with Flutter Storage SDK

Topics:

29.2.1 Uploading a File

The following upload methods are supported in Flutter SDK:

  • Upload from a file

  • Upload using raw data

  • Update file metadata

29.2.1.1 Flutter SDK Upload Examples

Upload File Data from InMemory to Oracle Backend for Firebase Storage

final storage = FusabaseStorage.instance;
final recipeRef =
    storage.ref('recipes/Scott/Cookies/main.jpg');

// Placeholder file data
final File = Uint8List.fromList(
  'fake image content'.codeUnits,
);

await recipeRef.putData(File);

print('Uploaded placeholder file');

Upload File Metadata

final recipeRef =
    storage.ref('recipes/Scott/Cookies/main.jpg');

final file =
    Uint8List.fromList('fake image content'.codeUnits);

final metadata = SettableMetadata(
  contentType: 'image/jpeg',
  customMetadata: {
    'recipeId': 'Cookies',
    'owner': 'Scott',
  },
);

await recipeRef.putData(file, metadata);

print('Uploaded with metadata');

29.2.2 Managing and Monitoring Uploads

The Flutter SDK enables you to manage uploads using the pause(), resume(), and cancel() methods.

The following methods monitor the state of the upload:

  • running

  • paused

  • success

  • cancelled

  • error

The following objects are also used:

  • UploadTask: UploadTask is the primary object that handles the upload of files to Oracle Backend for Firebase Storage. It provides methods and properties to track the upload progress, manage task states, and get notifications of completion or failure.

  • TaskSnapshot:TaskSnapshot is an object that provides real-time information about the current state of the upload. It contains useful properties, such as the number of bytes transferred and the total bytes of the file being uploaded, which are used to calculate and display the upload progress.

  • Snapshot Events: Oracle Backend for Firebase Storage provides snapshot events that notify you of changes in the upload process. You can listen to these events to update the UI, track progress, and handle success or failure.

  • Task States: The state of the upload task can be one of the following:

    • Running: The upload is in progress.

    • Success: The upload has completed successfully.

    • Failure: The upload has failed due to network issues, timeout, and so on.

29.2.2.1 Managing and Monitoring Uploads Examples

Managing and Monitoring an Upload

Future<void> uploadRecipeImage() async {
  // Get the application documents directory
  final appDocDir = await getApplicationDocumentsDirectory();
  final filePath = "${appDocDir.absolute}/recipes/recipe.jpg"; // Path to file
  final file = File(filePath); // The file to upload

  // Create file metadata (content type for image/jpeg)
  final metadata = SettableMetadata(contentType: "image/jpeg");

  // Create a reference to Fusabase Storage
  final storageRef = FusabaseStorage.instance.ref();

  // Start the upload task
  final uploadTask = storageRef
      .child("recipes/images/recipe.jpg") // Specify file path
      .putFile(file, metadata);

  // Listen for state changes, progress, and completion
  uploadTask.snapshotEvents.listen((TaskSnapshot taskSnapshot) {
    switch (taskSnapshot.state) {
      case TaskState.running:
        // Calculate and print upload progress
        final progress = 100.0 * (taskSnapshot.bytesTransferred / taskSnapshot.totalBytes);
        print("Upload is $progress% complete.");
        break;
      case TaskState.paused:
        print("Upload is paused.");
        break;
      case TaskState.canceled:
        print("Upload was canceled.");
        break;
      case TaskState.error:
        print("Upload failed due to an error.");
        break;
      case TaskState.success:
        print("Upload successful!");
        break;
    }
  });
}

29.3 Uploading with Java Android Storage SDK

Topics:

29.3.1 Uploading a File

The following upload methods are supported in Java Android SDK:

  • Upload using InMemory space

  • Upload using stream

  • Upload from local file

  • Update file metadata

  • Limitation

29.3.1.1 Java Android SDK Upload Examples

Upload File Data from InMemory to Oracle Backend for Firebase Storage

import com.oracle.mobile.fusabase.storage.Storage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.UploadTask;
import android.util.Log;

Storage storage = Storage.getInstance();

StorageReference recipeRef = storage.getReference("recipes/Scott/Cookies/main.jpg");

byte[] fileData = "fake image content".getBytes();

UploadTask uploadTask = recipeRef.putBytes(fileData);

uploadTask.addOnSuccessListener(taskSnapshot -> {
    Log.d(TAG, "Uploaded placeholder file successfully");
}).addOnFailureListener(exception -> {
    Log.w(TAG, "Upload failed", exception);
});

Upload File Metadata

import com.oracle.mobile.fusabase.storage.Storage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.UploadTask;
import android.util.Log;

Storage storage = Storage.getInstance();

// Create storage reference
StorageReference recipeRef = storage.getReference("recipes/Scott/Cookies/main.jpg");

// Create placeholder data (equivalent to Blob)
byte[] fileData = "fake image content".getBytes();

// Upload the data
UploadTask uploadTask = recipeRef.putBytes(fileData);

// Add completion listener
uploadTask.addOnSuccessListener(taskSnapshot -> {
    Log.d(TAG, "Uploaded placeholder file successfully");
    // You can get metadata here if needed
    // Uri downloadUrl = taskSnapshot.getDownloadUrl();
}).addOnFailureListener(exception -> {
    Log.w(TAG, "Upload failed", exception);
});

Upload File Metadata

import com.oracle.mobile.fusabase.storage.Storage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.UploadTask;
import android.util.Log;

Storage storage = Storage.getInstance();

// Create storage reference
StorageReference recipeRef = storage.getReference("recipes/Scott/Cookies/main.jpg");

// Create placeholder data (equivalent to Blob)
byte[] fileData = "fake image content".getBytes();

// Upload the data
UploadTask uploadTask = recipeRef.putBytes(fileData);

// Add completion listener
uploadTask.addOnSuccessListener(taskSnapshot -> {
    Log.d(TAG, "Uploaded placeholder file successfully");
    // You can get metadata here if needed
    // Uri downloadUrl = taskSnapshot.getDownloadUrl();
}).addOnFailureListener(exception -> {
    Log.w(TAG, "Upload failed", exception);
});

Upload Data from an Input Stream

import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.UploadTask;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

Storage storage = FusabaseStorage.getInstance();
        
/// Create storage reference
StorageReference fileRef = storage.getReference("uploads/stream-example.txt");

// Create input stream with data (you would typically get this from a file or network)
String data = "This is data from an InputStream";
InputStream stream = new ByteArrayInputStream(data.getBytes());

// Upload using putStream
UploadTask uploadTask = fileRef.putStream(stream);

// Monitor upload progress
uploadTask.addOnProgressListener(snapshot -> {
    double progress = (snapshot.getBytesTransferred() * 100.0) / snapshot.getTotalByteCount();
    Log.d(TAG, "Upload progress: " + progress + "%");
});

// Handle successful upload
uploadTask.addOnSuccessListener(taskSnapshot -> {
    Log.d(TAG, "Stream upload completed successfully");
});

// Handle upload failure
uploadTask.addOnFailureListener(exception -> {
    Log.e(TAG, "Stream upload failed", exception);
});

Upload Data from a File using PutFile

import com.oracle.mobile.fusabase.storage.Storage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.UploadTask;
import android.net.Uri;
import android.util.Log;

Storage storage = Storage.getInstance();

// Get root storage reference
StorageReference storageRef = storage.getReference();

// Example file URI (you'd typically get this from a file picker or camera)
Uri fileUri = Uri.parse("file://path/to/your/file.jpg");

// Reference where the file will be uploaded
StorageReference fileRef = storageRef.child("recipes/Scott/Cookies/" + fileUri.getLastPathSegment());

// Upload the file using putFile
UploadTask uploadTask = fileRef.putFile(fileUri);

// Add success listener
uploadTask.addOnSuccessListener(taskSnapshot -> {
    Log.d(TAG, "File uploaded successfully");
    // You can get the download URL if needed
    // Uri downloadUri = taskSnapshot.getDownloadUrl();
});

29.3.2 Managing and Monitoring Uploads

The Oracle Backend for Firebase Android SDK uses a listener-based approach for monitoring upload task states. Multiple specialized listeners track progress, pause, resume, success, and failure states during an upload task. These listeners provide information about the progress in an upload through snapshot properties such as bytesTransferred and totalByteCount.

You can manage uploads using the pause(), resume(), and cancel() methods.

The following methods monitor the upload activity:

  • OnProgressListener
  • OnPausedListener
  • OnSuccessListener
  • OnFailureListener

Following are the support properties of UploadTask.TaskSnapshot.

  • bytesTransferred: Returns the number of bytes transferred so far (long value)

  • totalByteCount: Returns the total number of bytes to be transferred (long value)

  • metadata: Returns the StorageMetadata object associated with the upload

  • getStorage(): Returns the StorageReference for the upload destination
  • getError(): Returns the Exception if the upload failed, null otherwise

29.3.2.1 Managing and Monitoring Uploads Examples

Managing and Monitoring an Upload

import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.UploadTask;
import android.util.Log;

Storage storage = FusabaseStorage.getInstance();
        
// File data to upload (for demonstration, replace with actual file)
byte[] fileData = "Hello, world!".getBytes();

// Create a reference to Storage location
StorageReference storageRef = storage.getReference();
StorageReference fileRef = storageRef.child("uploads/example.txt");

// Start the upload task
UploadTask uploadTask = fileRef.putBytes(fileData);

// Monitor the upload progress
uploadTask.addOnProgressListener(snapshot -> {
    long bytesTransferred = snapshot.getBytesTransferred();
    long totalBytes = snapshot.getTotalByteCount();
    double progress = (bytesTransferred * 100.0) / totalBytes;
    
    Log.d(TAG, "Upload is " + progress + "% done");
    Log.d(TAG, "Bytes Transferred: " + bytesTransferred);
    Log.d(TAG, "Total Bytes: " + totalBytes);
    
    // Handle paused state
    if (uploadTask.isPaused()) {
        Log.d(TAG, "Upload is paused");
    }
});

uploadTask.addOnFailureListener(exception -> {
    // Handle upload errors
    Log.e(TAG, "Upload failed", exception);
});

uploadTask.addOnSuccessListener(taskSnapshot -> {
    // Handle successful upload completion
    Log.d(TAG, "Upload completed successfully!");
});

// Simulate pause after 3 seconds
new Handler(Looper.getMainLooper()).postDelayed(() -> {
    if (uploadTask.pause()) {
        Log.d(TAG, "Upload paused after 3 seconds");
    }
}, 3000);

// Simulate resume after 6 seconds
new Handler(Looper.getMainLooper()).postDelayed(() -> {
    if (uploadTask.resume()) {
        Log.d(TAG, "Upload resumed after 6 seconds");
    }
}, 6000);

// Simulate cancel after 9 seconds
new Handler(Looper.getMainLooper()).postDelayed(() -> {
    if (uploadTask.cancel()) {
        Log.d(TAG, "Upload canceled after 9 seconds");
    }
}, 9000);

29.4 Uploading with Swift iOS Storage SDK

Topics:

29.4.1 Uploading a File

The following upload methods are supported in Swift iOS SDK:

  • Upload data from InMemory

  • Upload from a local file

  • Update file metadata

29.4.1.1 Swift iOS SDK Upload Examples

Upload File Data from InMemory to Oracle Backend for Firebase Storage

import FusabaseStorage

let storage = Storage.storage()
let recipeRef = storage.reference(withPath: "recipes/Scott/Cookies/main.jpg")

let placeholderContent = "fake image content"
let fileData = Data(placeholderContent.utf8)

recipeRef.putData(fileData, metadata: nil) { metadata, error in
    if let error = error {
        print("Upload failed: \(error.localizedDescription)")
    } else {
        print("Uploaded placeholder file")
    }
}

Upload File Metadata

import FusabaseStorage

let storage = Storage.storage()
let recipeRef = storage.reference(withPath: "recipes/Scott/Cookies/main.jpg")

let placeholderContent = "fake image content"
let fileData = Data(placeholderContent.utf8)

let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
metadata.cacheControl = "public,max-age=3600"
metadata.customMetadata = [
    "recipeId": "Cookies",
    "owner": "Scott"
]

// Upload with metadata
recipeRef.putData(fileData, metadata: metadata) { uploadedMetadata, error in
    if let error = error {
        print("Upload failed: \(error.localizedDescription)")
    } else {
        print("Uploaded with metadata")
    }
}

Upload Data from a File using PutFile

import FusabaseStorage

let storage = Storage.storage()

// Get root storage reference
let storageRef = storage.reference()

// Example file URL (you'd typically get this from a file picker or camera)
let fileURL = URL(fileURLWithPath: "/path/to/your/file.jpg")

// Reference where the file will be uploaded
let fileName = fileURL.lastPathComponent
let fileRef = storageRef.child("recipes/Scott/Cookies/\(fileName)")

// Upload the file
let uploadTask = fileRef.putFile(from: fileURL)

uploadTask.observe(.success) { snapshot in
    print("File uploaded successfully")
}

29.4.2 Managing and Monitoring Uploads

The observe(:handler:) method plays a crucial role in monitoring the state of a file upload. It tracks the progress, pause, resume, success, and failure states during an upload task. The observe method is used to observe the status of a file upload, and it provides information about the progress of the upload through snapshot properties such as progress.completedUnitCount and progress.totalUnitCount.

You can manage uploads using the pause(), resume(), and cancel() methods.

The observe method monitors the upload activity. Following are the support properties of Upload Task Snapshot:

  • progress
    • Type: Progress?
    • Description: Contains information about the upload progress, including bytes transferred and total bytes.
    • Sub-properties:
      • progress.completedUnitCount: Number of bytes transferred so far

      • progress.totalUnitCount: Total number of bytes expected

  • status
    • Type: StorageTaskStatus
    • Description: The current status of the upload task (unknown, resume, progress, pause, success, failure).
  • metadata
    • Type: StorageMetadata?
    • Description: The server-returned metadata for the uploaded object (available after successful completion).
  • error
    • Type: Error?
    • Description: The error that caused the upload to fail (available when status is failure).
  • task
    • Type: StorageTask
    • Description: The upload task instance that produced this snapshot.
  • reference
    • Type: StorageReference
    • Description: The storage reference where the file is being uploaded.
29.4.2.1 Managing and Monitoring Uploads Examples

Managing and Monitoring an Upload

import FusabaseStorage

// File to upload (for demonstration, replace with actual data)
let fileData = "Hello, world!".data(using: .utf8)!  // Example data

// Create a reference to Storage location
let storage = Storage.storage()
let storageRef = storage.reference().child("uploads/example.txt")

// Start the upload task
let uploadTask = storageRef.putData(fileData)

// Monitor the upload progress - equivalent to 'state_changed'
uploadTask.observe(.progress) { snapshot in
    if let progress = snapshot.progress {
        let progressPercent = (Double(progress.completedUnitCount) / Double(progress.totalUnitCount)) * 100
        print("Upload is \(progressPercent)% done")
        print("Bytes Transferred: \(progress.completedUnitCount)")
        print("Total Bytes: \(progress.totalUnitCount)")
        print("Current Upload State: \(snapshot.status)")
    }
    
    // Handle pause state
    if snapshot.status == .pause {
        print("Upload paused")
    }
}

uploadTask.observe(.pause) { snapshot in
    print("Upload paused")
}

uploadTask.observe(.resume) { snapshot in
    print("Upload resumed")
}

// Handle upload errors - equivalent to error callback
uploadTask.observe(.failure) { snapshot in
    print("Upload failed: \(snapshot.error?.localizedDescription ?? "Unknown error")")
}

// Handle successful upload completion - equivalent to completion callback
uploadTask.observe(.success) { snapshot in
    print("Upload completed successfully!")
    if let metadata = snapshot.metadata {
        print("File size: \(metadata.size ?? 0) bytes")
    }
}

// Simulate pause after 3 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    uploadTask.pause()
    print("Upload paused after 3 seconds")
}

// Simulate resume after 6 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
    uploadTask.resume()
    print("Upload resumed after 6 seconds")
}

// Simulate cancel after 9 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 9) {
    uploadTask.cancel()
    print("Upload canceled after 9 seconds")
}

29.5 Downloading with Storage SDK

getDownloadURL

getDownloadURL returns a time-stable, publicly accessible HTTPS URL for an Oracle Backend for Firebase Storage object.

The file is not downloaded by the SDK; you download it yourself using:

  • Browser

  • <img>, <video>

  • fetch()

  • Any HTTP client

Security rule is validated only during generation of the URL. The URL is valid until the REST endpoint is dropped from the schema.

import { ref } from "fusabase/storage";

const recipeRef = ref(getStorage(), "recipes/pasta.pdf");

const url = await getDownloadURL(recipeRef);
window.open(url);

const recipeRef = storage.ref("recipes/pasta.pdf");

const url = await recipeRef.getDownloadURL();
window.open(url);

import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import android.net.Uri;
import android.util.Log;

Storage storage = FusabaseStorage.getInstance();
        
// Create reference to the file
StorageReference ref = storage.getReference("recipes/pasta.pdf");

// Get download URL
ref.getDownloadUrl().addOnSuccessListener(uri -> {
    String url = uri.toString();
    Log.d(TAG, "Download URL: " + url);
}).addOnFailureListener(exception -> {
    Log.e(TAG, "Failed to get download URL", exception);
});

import FusabaseStorage

// Create a reference to the file
let storage = Storage.storage()
let ref = storage.reference(withPath: "recipes/pasta.pdf")

let url = try await ref.downloadURL()
print(url)
final ref = FusabaseStorage.instance.ref('recipes/pasta.pdf');
final url = await ref.getDownloadURL();

print(url);

getBlob

getBlob downloads the file as a BLOB object (useful for working with binary data). It is web-only and designed for browser-based file handling. It is stored in browser memory with its size limited by the device or browser.

import { ref, getStorage, getBlob } from "fusabase/storage";

const storage = getStorage();
const recipeRef = ref(storage, "recipes/cake.jpg");

const blob = await getBlob(recipeRef);

// Create a local object URL
const imgUrl = URL.createObjectURL(blob);
document.querySelector("img").src = imgUrl;

getBytes

getBytes downloads a file from Storage entirely into memory as a byte array. It is best for small files that you want to process immediately (text, JSON, small images).

import { ref, getStorage, getBytes } from "fusabase/storage";

const storage = getStorage(app);

const recipeRef = ref(storage, "recipes/biryani.txt");

// Optional size limit (recommended)
const MAX_SIZE = 1024 * 1024; // 1 MB

const bytes = await getBytes(recipeRef, MAX_SIZE);

// Convert bytes → text
const recipe = new TextDecoder().decode(bytes);
console.log(recipe);
import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import android.util.Log;

Storage storage = FusabaseStorage.getInstance();
        
StorageReference recipeRef = storage.getReference("recipes/biryani.txt");

// Optional size limit (recommended)
long MAX_SIZE = 1024 * 1024; // 1 MB

// Download bytes
recipeRef.getBytes(MAX_SIZE).addOnSuccessListener(bytes -> {
    // Convert bytes to text
    String recipe = new String(bytes);
    Log.d(TAG, recipe);
}).addOnFailureListener(exception -> {
    Log.e(TAG, "Failed to download bytes", exception);
});

getFile

getFile is a Storage Android API that downloads a file directly to disk (streaming), without loading it fully into memory.

import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.FileDownloadTask;
import android.content.Context;
import android.util.Log;
import java.io.File;

Storage storage = FusabaseStorage.getInstance();
        
// Create storage reference
StorageReference recipeRef = storage.getReference("recipes/pasta.pdf");

// Create local file in cache directory
File localFile = new File(getCacheDir(), "pasta.pdf");

// Download file to local filesystem
FileDownloadTask downloadTask = recipeRef.getFile(localFile);

downloadTask.addOnSuccessListener(taskSnapshot -> {
    // File fully downloaded
    Log.d(TAG, "File downloaded successfully to: " + localFile.getAbsolutePath());
});
import FusabaseStorage

let storage = Storage.storage()

// Create storage reference
let recipeRef = storage.reference(withPath: "recipes/pasta.pdf")

// Create local file URL in cache directory
let cacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
let localFileURL = cacheDirectory.appendingPathComponent("pasta.pdf")

// Download file to local filesystem
let downloadTask = recipeRef.write(toFile: localFileURL)

downloadTask.observe(.success) { snapshot in
    print("File downloaded successfully to: \(localFileURL.path)")
}

Download with Progress Tracking

import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.FileDownloadTask;
import android.content.Context;
import android.util.Log;
import java.io.File;

Storage storage = FusabaseStorage.getInstance();
        
// Create storage reference
StorageReference recipeRef = storage.getReference("recipes/pasta.pdf");

// Create local file in cache directory
File localFile = new File(getCacheDir(), "pasta.pdf");

// Download file to local filesystem
FileDownloadTask downloadTask = recipeRef.getFile(localFile);

downloadTask.addOnSuccessListener(taskSnapshot -> {
    // File fully downloaded
    Log.d(TAG, "File downloaded successfully to: " + localFile.getAbsolutePath());
}).addOnFailureListener(exception -> {
    // Handle download failure
    Log.e(TAG, "File download failed", exception);
}).addOnProgressListener(snapshot -> {
    // Optional: Monitor download progress
    double progress = (snapshot.getBytesTransferred() * 100.0) / snapshot.getTotalByteCount();
    Log.d(TAG, "Download progress: " + progress + "%");
});
import FusabaseStorage

let storage = Storage.storage()

// Create storage reference
let recipeRef = storage.reference(withPath: "recipes/pasta.pdf")

// Create local file URL in cache directory

let localFileURL = FileManager.default
    .temporaryDirectory
    .appendingPathComponent("pasta.pdf")
// Download file to local filesystem
let downloadTask = recipeRef.write(toFile: localFileURL)

downloadTask.observe(.success) { snapshot in
    // File fully downloaded
    print("File downloaded successfully to: \(localFileURL.path)")
}

downloadTask.observe(.failure) { snapshot in
    // Handle download failure
    print("File download failed: \(snapshot.error?.localizedDescription ?? "Unknown error")")
}

downloadTask.observe(.progress) { snapshot in
    // Optional: Monitor download progress
    if let progress = snapshot.progress {
        let progressPercent = (Double(progress.completedUnitCount) * 100.0) / Double(progress.totalUnitCount)
        print("Download progress: \(progressPercent)%")
    }
}

getData

getData (or getBytes on Android) downloads the entire file into memory (RAM) as a byte array / Data. The method enables downloads of the file as raw data, which is useful for small files. Properties such as maxSize prevents OOM (Out Of Memory).

The following are the platforms and their corresponding APIs:

iOS (Swift) getData(maxSize:)
Android getBytes(long maxSize)
Flutter getData([maxSize])
import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import android.util.Log;

Storage storage = FusabaseStorage.getInstance();
StorageReference ref = storage.getReference("recipes/biryani.txt");

// Set maximum download size (recommended for security)
long MAX_SIZE = 1024 * 1024; // 1MB

// Download bytes from storage
ref.getBytes(MAX_SIZE)
    .addOnSuccessListener(bytes -> {
        // Convert bytes to string and display
        String recipe = new String(bytes);
        System.out.println(recipe);
        Log.d(TAG, "Downloaded content: " + recipe);
    })
    .addOnFailureListener(exception -> {
        // Handle download failure
        Log.e(TAG, "Failed to download bytes", exception);
        exception.printStackTrace();
    });
import FusabaseStorage

let storage = Storage.storage()
let recipeRef = storage.reference(withPath: "recipes/biryani.txt")

// Optional size limit (recommended)
let maxSize: Int64 = 1024 * 1024 // 1 MB

// Download bytes
recipeRef.getData(maxSize: maxSize) { data, error in
    if let error = error {
        print("Failed to download bytes: \(error.localizedDescription)")
        return
    }
    
    if let data = data {
        // Convert bytes to text
        if let recipe = String(data: data, encoding: .utf8) {
            print(recipe)
        } else {
            print("Failed to convert data to string")
        }
    }
}
final ref = storage.ref('recipes/biryani.txt');

final data = await ref.getData(1024 * 1024);
final recipe = String.fromCharCodes(data!);

print(recipe);

writeToFile

writeToFile downloads a Storage object directly to a local file on disk, streaming the data instead of loading it into memory.

The following are the platforms and their corresponding APIs:

iOS (Swift) write(toFile:)
Flutter (Dart) writeToFile(File)
import FusabaseStorage

let ref = Storage.storage()
    .reference(withPath: "recipes/pasta.pdf")

let localURL = FileManager.default
    .temporaryDirectory
    .appendingPathComponent("pasta.pdf")

let task = ref.write(toFile: localURL)

task.observe(.progress) { snapshot in
    let progress =
        Double(snapshot.progress!.completedUnitCount) /
        Double(snapshot.progress!.totalUnitCount)
    print("Download \(progress * 100)%")
}

task.observe(.success) { _ in
    print("Recipe downloaded to \(localURL)")
}
final ref =
    storage.ref('recipes/pasta.pdf');

final file =
    File('${Directory.systemTemp.path}/pasta.pdf');

final task = ref.writeToFile(file);

task.snapshotEvents.listen((snapshot) {
  final progress =
      snapshot.bytesTransferred / snapshot.totalBytes;
  print('Download ${(progress * 100).toStringAsFixed(0)}%');
});

29.5.1 Comparison of Download Methods

The following table provides a comparison of the download methods regarding their use cases and limitations.

API Use Case Limitation
writeToFile Large files No in-memory access
getBytes() Small text/JSON Memory limit
getBlob() (Web) Browser usage Size limits
getDownloadURL() Public access Exposed URL

The following table compares the features of the getData and WriteToFile methods:

Feature getData WriteToFile
Memory usage High Low
File size Small Large
Streaming Not Available Available
Progress Not Available Available
Use case Parse text Save file

Example

const storage = getStorage();
const recipeRef = ref(storage, "recipes/pasta.pdf");

getDownloadURL(recipeRef)
  .then((url) => {
    // Open or download the recipe
    window.open(url);
  })
  .catch(console.error);

const recipeRef_b = ref(getStorage(), "recipes/pasta.pdf");

const blob = await getBlob(recipeRef_b);
console.log("Recipe blob:", blob);

import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import android.util.Log;

Storage storage = FusabaseStorage.getInstance();
        
// Create storage reference
StorageReference recipeRef = storage.getReference("recipes/pasta.pdf");

// Download blob data (equivalent to getBlob in JavaScript)
recipeRef.getBytes(Long.MAX_VALUE).addOnSuccessListener(bytes -> {
    // In Android, we work with byte arrays instead of Blob objects
    Log.d(TAG, "Recipe blob size: " + bytes.length + " bytes");
    
}).addOnFailureListener(exception -> {
    Log.e(TAG, "Failed to download blob", exception);
});
import FusabaseStorage

let ref = Storage.storage()
    .reference(withPath: "recipes/pasta.pdf")

let localURL = FileManager.default
    .temporaryDirectory
    .appendingPathComponent("pasta.pdf")

ref.write(toFile: localURL) { url, error in
    if let error = error {
        print(error)
    } else {
        print("Recipe saved at \(url!)")
    }
}
final ref = FusabaseStorage.instance.ref('recipes/pasta.pdf');
final url = await ref.getDownloadURL();

print(url);

final ref_p = FusabaseStorage.instance.ref('recipes/pasta.pdf');
final file = File('${Directory.systemTemp.path}/pasta.pdf');

await ref_p.writeToFile(file);

29.6 File Management Operations

Delete a File

// Initialize Storage
const storage = getStorage(app);

// Get a reference to the file
const fileRef = ref(storage, 'path/to/your/file');

// Delete the file
deleteObject(fileRef).then(() => {
  console.log('File deleted successfully!');
}).catch((error) => {
  console.error('Error deleting file:', error);
});

// Reference to the file you want to delete
const storageRef = storage.ref('path/to/your/file');

// Delete the file
storageRef.delete().then(() => {
  console.log('File deleted successfully!');
}).catch((error) => {
  console.error('Error deleting file:', error);
});
import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import android.util.Log;

Storage storage = FusabaseStorage.getInstance();
        
// Create storage reference
StorageReference storageRef = storage.getReference("path/to/your/file");
        
// Delete the file
storageRef.delete().addOnSuccessListener(aVoid -> {
    // File deleted successfully
    Log.d(TAG, "File deleted successfully!");
}).addOnFailureListener(exception -> {
    // Handle failure
    Log.e(TAG, "Error deleting file: " + exception.getMessage());
});

import FusabaseStorage
let storageRef = Storage.storage().reference().child("path/to/file")
do {
try await storageRef.delete()
print("File deleted")
} catch {
print("Delete failed: \(error)")
}
// Reference to the file you want to delete
final storageRef = storage.instance.ref().child('path/to/your/file');

// Delete the file
storageRef.delete().then((_) {
  print("File deleted successfully!");
}).catchError((error) {
  print("Error deleting file: $error");
});

List Files

import { ref } from "fusabase/storage";

const storageRef = ref('path/to/your/folder');

// List files
list(storageRef).then((result) => {
  result.items.forEach(item => {
    console.log('File: ', item.name);
  });
}).catch((error) => {
  console.error('Error listing files: ', error);
});

const storageRef = storage.ref('path/to/your/folder');

// List files
storageRef.list().then((result) => {
  result.items.forEach(item => {
    console.log('File: ', item.name);
  });
}).catch((error) => {
  console.error('Error listing files: ', error);
});
import com.oracle.mobile.fusabase.storage.FusabaseStorage;
import com.oracle.mobile.fusabase.storage.StorageReference;
import com.oracle.mobile.fusabase.storage.ListResult;
import android.util.Log;

Storage storage = FusabaseStorage.getInstance();
        
// Get reference to the folder
StorageReference storageRef = storage.getReference("path/to/your/folder");

// List all files in the folder
storageRef.listAll().addOnSuccessListener(listResult -> {
    // Iterate through all items (files)
    for (StorageReference item : listResult.getItems()) {
        Log.d(TAG, "File: " + item.getName());
    }
    
    // You can also list subfolders if needed
    for (StorageReference prefix : listResult.getPrefixes()) {
        Log.d(TAG, "Folder: " + prefix.getName());
    }
}).addOnFailureListener(exception -> {
    Log.e(TAG, "Error listing files: " + exception.getMessage());
});

import FusabaseStorage

let storageRef = Storage.storage().reference(withPath: "path/to/your/folder")

// List files
storageRef.listAll { (result, error) in
    if let error = error {
        print("Error listing files: \(error.localizedDescription)")
        return
    }

    // Process the files
    for item in result!.items {
        print("File: \(item.name)")
    }
}
final storageRef = storage.ref().child('path/to/your/folder');

// List files
Future<void> listFiles() async {
  try {
    final ListResult result = await storageRef.listAll();

    // Process files
    for (var item in result.items) {
      print('File: ${item.name}');
    }
  } catch (error) {
    print('Error listing files: $error');
  }
}

// Fetch the files
listFiles();