העלאת קבצים באמצעות Cloud Storage ב-Flutter

בעזרת Cloud Storage for Firebase אפשר להעלות בקלות ובמהירות קבצים לקטגוריה של Cloud Storage ש-Firebase מספקת ומנהלת.

העלאת קבצים

כדי להעלות קובץ ל-Cloud Storage, קודם צריך ליצור הפניה לנתיב המלא של הקובץ, כולל שם הקובץ.

// Create a storage reference from our app
final storageRef = FirebaseStorage.instance.ref();

// Create a reference to "mountains.jpg"
final mountainsRef = storageRef.child("mountains.jpg");

// Create a reference to 'images/mountains.jpg'
final mountainImagesRef = storageRef.child("images/mountains.jpg");

// While the file names are the same, the references point to different files
assert(mountainsRef.name == mountainImagesRef.name);
assert(mountainsRef.fullPath != mountainImagesRef.fullPath);

אחרי שיוצרים את ההפניה המתאימה, צריך להפעיל את השיטה putFile(),‏ putString() או putData() כדי להעלות את הקובץ ל-Cloud Storage.

אי אפשר להעלות נתונים עם הפניה לשורש הקטגוריה ב-Cloud Storage. ההפניה צריכה להפנות לכתובת URL של צאצא.

העלאה מקובץ

כדי להעלות קובץ, קודם צריך לקבל את הנתיב המוחלט למיקום שלו במכשיר. לדוגמה, אם קובץ קיים בספריית המסמכים של האפליקציה, אפשר להשתמש בחבילה הרשמית path_provider כדי ליצור נתיב לקובץ ולהעביר אותו ל-putFile():

Directory appDocDir = await getApplicationDocumentsDirectory();
String filePath = '${appDocDir.absolute}/file-to-upload.png';
File file = File(filePath);

try {
  await mountainsRef.putFile(file);
} on firebase_core.FirebaseException catch (e) {
  // ...
}

העלאה ממחרוזת

אפשר להעלות נתונים כמחרוזת קודמת, base64, base64url או data_url, באמצעות השיטה putString(). לדוגמה, כדי להעלות מחרוזת טקסט שמקודדת ככתובת URL של נתונים:

String dataUrl = 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==';

try {
  await mountainsRef.putString(dataUrl, format: PutStringFormat.dataUrl);
} on FirebaseException catch (e) {
  // ...
}

העלאת נתונים גולמיים

במקרים שבהם לא מעשי להעלות מחרוזת או File, אפשר להעלות נתונים מוקלדים ברמה נמוכה יותר בצורת Uint8List. במקרה כזה, צריך להפעיל את השיטה putData() עם הנתונים:

try {
  // Upload raw data.
  await mountainsRef.putData(data);
} on firebase_core.FirebaseException catch (e) {
  // ...
}

קבלת כתובת URL להורדה

אחרי העלאת קובץ, אפשר לקבל כתובת URL להורדת הקובץ על ידי קריאה ל-method‏ getDownloadUrl() ב-Reference:

await mountainsRef.getDownloadURL();

הוספת מטא-נתונים של קובץ

אפשר גם לכלול מטא-נתונים כשאתם מעלים קבצים. המטא-נתונים האלה מכילים מאפייני מטא-נתונים אופייניים של קבצים, כמו contentType (שנקרא בדרך כלל סוג MIME). השיטה putFile() מסיקה באופן אוטומטי את סוג ה-MIME מהתוסף File, אבל אפשר לשנות את הסוג שזוהה באופן אוטומטי על ידי ציון contentType במטא-נתונים. אם לא תספקו את הערך של contentType ומערכת Cloud Storage לא תוכל להסיק ערך ברירת מחדל מהסיומת של הקובץ, היא תשתמש ב-application/octet-stream. שימוש במטא-נתונים של קבצים

try {
  await mountainsRef.putFile(file, SettableMetadata(
    contentType: "image/jpeg",
  ));
} on firebase_core.FirebaseException catch (e) {
  // ...
}

נהל העלאות

בנוסף להפעלת העלאות, אפשר להשהות, להמשיך ולבטל העלאות באמצעות השיטות pause(), ‏resume() ו-cancel(). אירועי השהיה והפעלה מחדש מפעילים שינויים בסטטוס pause ו-progress, בהתאמה. ביטול ההעלאה גורם לכך שההעלאה נכשלת עם שגיאה שמציינת שההעלאה בוטלה.

final task = mountainsRef.putFile(largeFile);

// Pause the upload.
bool paused = await task.pause();
print('paused, $paused');

// Resume the upload.
bool resumed = await task.resume();
print('resumed, $resumed');

// Cancel the upload.
bool canceled = await task.cancel();
print('canceled, $canceled');

מעקב אחר התקדמות ההעלאה

אפשר להאזין למקור האירועים של המשימה כדי לטפל בהצלחה, בכישלון, בהתקדמות או בהשהיות של משימה ההעלאה:

סוג האירוע שימוש רגיל
TaskState.running האירוע הזה נשלח מדי פעם במהלך העברת הנתונים, וניתן להשתמש בו כדי לאכלס אינדיקטור של העלאה/הורדה.
TaskState.paused האירוע הזה נשלח בכל פעם שהמשימה מושהית.
TaskState.success האירוע הזה מופעל כשהמשימה הושלמה בהצלחה.
TaskState.canceled האירוע הזה נשלח בכל פעם שהמשימה מבוטלת.
TaskState.error האירוע הזה מופעל כשההעלאה נכשלה. זה יכול לקרות בגלל תפוגת זמן הקצוב לרשת, כשלים באימות או אם מבטלים את המשימה.
mountainsRef.putFile(file).snapshotEvents.listen((taskSnapshot) {
  switch (taskSnapshot.state) {
    case TaskState.running:
      // ...
      break;
    case TaskState.paused:
      // ...
      break;
    case TaskState.success:
      // ...
      break;
    case TaskState.canceled:
      // ...
      break;
    case TaskState.error:
      // ...
      break;
  }
});

טיפול בשגיאות

יש כמה סיבות לכך שעשויות להתרחש שגיאות בהעלאה, כולל הקובץ המקומי לא קיים או שהמשתמש לא קיבל הרשאה להעלות את הקובץ הרצוי. מידע נוסף על שגיאות זמין בקטע טיפול בשגיאות במסמכים.

דוגמה מלאה

בהמשך מופיעה דוגמה מלאה להעלאה עם מעקב אחר התקדמות וטיפול בשגיאות:

final appDocDir = await getApplicationDocumentsDirectory();
final filePath = "${appDocDir.absolute}/path/to/mountains.jpg";
final file = File(filePath);

// Create the file metadata
final metadata = SettableMetadata(contentType: "image/jpeg");

// Create a reference to the Firebase Storage bucket
final storageRef = FirebaseStorage.instance.ref();

// Upload file and metadata to the path 'images/mountains.jpg'
final uploadTask = storageRef
    .child("images/path/to/mountains.jpg")
    .putFile(file, metadata);

// Listen for state changes, errors, and completion of the upload.
uploadTask.snapshotEvents.listen((TaskSnapshot taskSnapshot) {
  switch (taskSnapshot.state) {
    case TaskState.running:
      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:
      // Handle unsuccessful uploads
      break;
    case TaskState.success:
      // Handle successful uploads on complete
      // ...
      break;
  }
});

עכשיו, אחרי שהעליתם קבצים, נסביר איך להוריד אותם מ-Cloud Storage.