הפקודה Cloud Storage for Firebase מאפשרת להעלות קבצים במהירות ובקלות לדלי Cloud Storage שסופק ומנוהל על ידי Firebase.
העלאת קבצים
כדי להעלות קובץ ל-Cloud Storage, קודם יוצרים הפניה לנתיב המלא של הקובץ, כולל שם הקובץ.
Kotlin
// Create a storage reference from our app val storageRef = storage.reference // Create a reference to "mountains.jpg" val mountainsRef = storageRef.child("mountains.jpg") // Create a reference to 'images/mountains.jpg' val mountainImagesRef = storageRef.child("images/mountains.jpg") // While the file names are the same, the references point to different files mountainsRef.name == mountainImagesRef.name // true mountainsRef.path == mountainImagesRef.path // false
Java
// Create a storage reference from our app StorageReference storageRef = storage.getReference(); // Create a reference to "mountains.jpg" StorageReference mountainsRef = storageRef.child("mountains.jpg"); // Create a reference to 'images/mountains.jpg' StorageReference mountainImagesRef = storageRef.child("images/mountains.jpg"); // While the file names are the same, the references point to different files mountainsRef.getName().equals(mountainImagesRef.getName()); // true mountainsRef.getPath().equals(mountainImagesRef.getPath()); // false
אחרי שיוצרים הפניה מתאימה, קוראים לשיטה putBytes()
, putFile()
או putStream()
כדי להעלות את הקובץ אל Cloud Storage.
אי אפשר להעלות נתונים עם הפניה לקטגוריית Cloud Storage הבסיסית. ההפניה צריכה להפנות לכתובת URL של אתר צאצא.
העלאה מנתונים בזיכרון
השיטה putBytes()
היא הדרך הפשוטה ביותר להעלות קובץ ל-Cloud Storage. putBytes()
מקבל byte[]
ומחזיר UploadTask
שאפשר להשתמש בו כדי לנהל ולעקוב אחרי סטטוס ההעלאה.
Kotlin
// Get the data from an ImageView as bytes imageView.isDrawingCacheEnabled = true imageView.buildDrawingCache() val bitmap = (imageView.drawable as BitmapDrawable).bitmap val baos = ByteArrayOutputStream() bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos) val data = baos.toByteArray() var uploadTask = mountainsRef.putBytes(data) uploadTask.addOnFailureListener { // Handle unsuccessful uploads }.addOnSuccessListener { taskSnapshot -> // taskSnapshot.metadata contains file metadata such as size, content-type, etc. // ... }
Java
// Get the data from an ImageView as bytes imageView.setDrawingCacheEnabled(true); imageView.buildDrawingCache(); Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); byte[] data = baos.toByteArray(); UploadTask uploadTask = mountainsRef.putBytes(data); uploadTask.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc. // ... } });
מכיוון ש-putBytes()
מקבל byte[]
, האפליקציה צריכה להחזיק את כל התוכן של קובץ בזיכרון בבת אחת. כדי להשתמש בפחות זיכרון, מומלץ להשתמש ב-putStream()
או ב-putFile()
.
העלאה משידור
השיטה putStream()
היא הדרך הכי מגוונת להעלות קובץ ל-Cloud Storage. putStream()
מקבל InputStream
ומחזיר UploadTask
שאפשר להשתמש בו כדי לנהל ולעקוב אחרי סטטוס ההעלאה.
Kotlin
val stream = FileInputStream(File("path/to/images/rivers.jpg")) uploadTask = mountainsRef.putStream(stream) uploadTask.addOnFailureListener { // Handle unsuccessful uploads }.addOnSuccessListener { taskSnapshot -> // taskSnapshot.metadata contains file metadata such as size, content-type, etc. // ... }
Java
InputStream stream = new FileInputStream(new File("path/to/images/rivers.jpg")); uploadTask = mountainsRef.putStream(stream); uploadTask.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc. // ... } });
העלאה מקובץ מקומי
אפשר להעלות קבצים מקומיים במכשיר, כמו תמונות וסרטונים מהמצלמה, באמצעות השיטה putFile()
. putFile()
מקבל File
ומחזיר UploadTask
שאפשר להשתמש בו כדי לנהל ולעקוב אחרי סטטוס ההעלאה.
Kotlin
var file = Uri.fromFile(File("path/to/images/rivers.jpg")) val riversRef = storageRef.child("images/${file.lastPathSegment}") uploadTask = riversRef.putFile(file) // Register observers to listen for when the download is done or if it fails uploadTask.addOnFailureListener { // Handle unsuccessful uploads }.addOnSuccessListener { taskSnapshot -> // taskSnapshot.metadata contains file metadata such as size, content-type, etc. // ... }
Java
Uri file = Uri.fromFile(new File("path/to/images/rivers.jpg")); StorageReference riversRef = storageRef.child("images/"+file.getLastPathSegment()); uploadTask = riversRef.putFile(file); // Register observers to listen for when the download is done or if it fails uploadTask.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc. // ... } });
קבלת כתובת URL להורדה
אחרי העלאת קובץ, אפשר לקבל כתובת URL להורדת הקובץ על ידי קריאה לשיטה getDownloadUrl()
ב-StorageReference
:
Kotlin
val ref = storageRef.child("images/mountains.jpg") uploadTask = ref.putFile(file) val urlTask = uploadTask.continueWithTask { task -> if (!task.isSuccessful) { task.exception?.let { throw it } } ref.downloadUrl }.addOnCompleteListener { task -> if (task.isSuccessful) { val downloadUri = task.result } else { // Handle failures // ... } }
Java
final StorageReference ref = storageRef.child("images/mountains.jpg"); uploadTask = ref.putFile(file); Task<Uri> urlTask = uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() { @Override public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception { if (!task.isSuccessful()) { throw task.getException(); } // Continue with the task to get the download URL return ref.getDownloadUrl(); } }).addOnCompleteListener(new OnCompleteListener<Uri>() { @Override public void onComplete(@NonNull Task<Uri> task) { if (task.isSuccessful()) { Uri downloadUri = task.getResult(); } else { // Handle failures // ... } } });
הוספת מטא-נתונים של קובץ
אפשר גם לכלול מטא-נתונים כשמעלים קבצים.
המטא-נתונים האלה מכילים מאפיינים אופייניים של מטא-נתונים של קבצים, כמו name
, size
ו-contentType
(שנקרא בדרך כלל סוג MIME). השיטה putFile()
מסיקה באופן אוטומטי את סוג ה-MIME מהתוסף File
, אבל אפשר לשנות את הסוג שזוהה אוטומטית על ידי ציון contentType
במטא-נתונים. אם לא תציינו contentType
ו-Cloud Storage לא יוכל להסיק ברירת מחדל מסיומת הקובץ, Cloud Storage ישתמש ב-application/octet-stream
. מידע נוסף על מטא-נתונים של קבצים זמין בקטע שימוש במטא-נתונים של קבצים.
Kotlin
// Create file metadata including the content type var metadata = storageMetadata { contentType = "image/jpg" } // Upload the file and metadata uploadTask = storageRef.child("images/mountains.jpg").putFile(file, metadata)
Java
// Create file metadata including the content type StorageMetadata metadata = new StorageMetadata.Builder() .setContentType("image/jpg") .build(); // Upload the file and metadata uploadTask = storageRef.child("images/mountains.jpg").putFile(file, metadata);
נהל העלאות
בנוסף להפעלת העלאות, אפשר להשהות, להמשיך ולבטל העלאות באמצעות הפונקציות pause()
, resume()
ו-cancel()
. השהיה והפעלה מחדש של אירועים
מעלות שינויים במצב pause
ו-progress
בהתאמה. ביטול העלאה גורם להעלאה להיכשל עם שגיאה שמציינת שההעלאה בוטלה.
Kotlin
uploadTask = storageRef.child("images/mountains.jpg").putFile(file) // Pause the upload uploadTask.pause() // Resume the upload uploadTask.resume() // Cancel the upload uploadTask.cancel()
Java
uploadTask = storageRef.child("images/mountains.jpg").putFile(file); // Pause the upload uploadTask.pause(); // Resume the upload uploadTask.resume(); // Cancel the upload uploadTask.cancel();
מעקב אחר התקדמות ההעלאה
אתם יכולים להוסיף רכיבי listener לטיפול בהצלחה, בכישלון, בהתקדמות או בהשהיות במשימת ההעלאה:
סוג ה-Listener | שימוש רגיל |
---|---|
OnProgressListener |
המאזין הזה מופעל מדי פעם בזמן העברת הנתונים, ואפשר להשתמש בו כדי לאכלס אינדיקטור של העלאה או הורדה. |
OnPausedListener |
המאזין הזה מופעל בכל פעם שהמשימה מושהית. |
OnSuccessListener |
המאזין הזה מופעל כשהמשימה מסתיימת בהצלחה. |
OnFailureListener |
המערכת קוראת ל-listener הזה בכל פעם שההעלאה נכשלת. זה יכול לקרות בגלל פסק זמן ברשת, כשלים בהרשאה או אם מבטלים את המשימה. |
הפונקציה OnFailureListener
מופעלת עם מופע של Exception
. הקריאה למאזינים אחרים מתבצעת באמצעות אובייקט UploadTask.TaskSnapshot
.
האובייקט הזה הוא תצוגה שלא ניתן לשנות של המשימה בזמן שהאירוע התרחש.
ל-UploadTask.TaskSnapshot
יש את המאפיינים הבאים:
נכס | סוג | תיאור |
---|---|---|
getDownloadUrl |
String |
כתובת URL שאפשר להשתמש בה כדי להוריד את האובייקט. זו כתובת URL ציבורית שאי אפשר לנחש אותה, ואפשר לשתף אותה עם לקוחות אחרים. הערך הזה מאוכלס אחרי שההעלאה מסתיימת. |
getError |
Exception |
אם המשימה נכשלה, השדה הזה יכיל את הסיבה לכך כחריגה. |
getBytesTransferred |
long |
המספר הכולל של בייטים שהועברו כשצולמה התמונה הזו. |
getTotalByteCount |
long |
המספר הכולל של בייטים שצפויים להיות מועלים. |
getUploadSessionUri |
String |
URI שאפשר להשתמש בו כדי להמשיך את המשימה הזו באמצעות קריאה נוספת ל-putFile. |
getMetadata |
StorageMetadata |
לפני שההעלאה מסתיימת, אלה המטא-נתונים שנשלחים לשרת. אלה המטא-נתונים שמוחזרים על ידי השרת אחרי שההעלאה מסתיימת. |
getTask |
UploadTask |
המשימה שיצרה את ה-snapshot הזה. אפשר להשתמש במשימה הזו כדי לבטל את ההעלאה, להשהות אותה או להמשיך אותה. |
getStorage |
StorageReference |
ה-StorageReference ששימש ליצירת UploadTask . |
הפונקציות UploadTask
event listener מספקות דרך פשוטה ויעילה למעקב אחרי אירועי העלאה.
Kotlin
// Observe state change events such as progress, pause, and resume // You'll need to import com.google.firebase.storage.component1 and // com.google.firebase.storage.component2 uploadTask.addOnProgressListener { (bytesTransferred, totalByteCount) -> val progress = (100.0 * bytesTransferred) / totalByteCount Log.d(TAG, "Upload is $progress% done") }.addOnPausedListener { Log.d(TAG, "Upload is paused") }
Java
// Observe state change events such as progress, pause, and resume uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount(); Log.d(TAG, "Upload is " + progress + "% done"); } }).addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() { @Override public void onPaused(UploadTask.TaskSnapshot taskSnapshot) { Log.d(TAG, "Upload is paused"); } });
טיפול בשינויים במחזור החיים של פעילות
ההעלאות ממשיכות ברקע גם אחרי שינויים במחזור החיים של הפעילות (למשל הצגת תיבת דו-שיח או סיבוב המסך). כל המאזינים שהיו מקושרים אליך יישארו מקושרים. אם הפונקציות האלה נקראות אחרי שהפעילות נעצרת, יכול להיות שיתקבלו תוצאות לא צפויות.
כדי לפתור את הבעיה הזו, צריך לרשום את המאזינים עם היקף פעילות
כדי לבטל את הרישום שלהם באופן אוטומטי כשהפעילות מפסיקה. לאחר מכן, משתמשים בשיטה getActiveUploadTasks
כשהפעילות מופעלת מחדש כדי לקבל משימות העלאה שעדיין פועלות או שהושלמו לאחרונה.
בדוגמה הבאה אפשר לראות איך עושים את זה וגם איך שומרים את נתיב ההפניה לאחסון שבו נעשה שימוש.
Kotlin
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) // If there's an upload in progress, save the reference so you can query it later outState.putString("reference", storageRef.toString()) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) // If there was an upload in progress, get its reference and create a new StorageReference val stringRef = savedInstanceState.getString("reference") ?: return storageRef = Firebase.storage.getReferenceFromUrl(stringRef) // Find all UploadTasks under this StorageReference (in this example, there should be one) val tasks = storageRef.activeUploadTasks if (tasks.size > 0) { // Get the task monitoring the upload val task = tasks[0] // Add new listeners to the task using an Activity scope task.addOnSuccessListener(this) { // Success! // ... } } }
Java
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // If there's an upload in progress, save the reference so you can query it later if (mStorageRef != null) { outState.putString("reference", mStorageRef.toString()); } } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); // If there was an upload in progress, get its reference and create a new StorageReference final String stringRef = savedInstanceState.getString("reference"); if (stringRef == null) { return; } mStorageRef = FirebaseStorage.getInstance().getReferenceFromUrl(stringRef); // Find all UploadTasks under this StorageReference (in this example, there should be one) List<UploadTask> tasks = mStorageRef.getActiveUploadTasks(); if (tasks.size() > 0) { // Get the task monitoring the upload UploadTask task = tasks.get(0); // Add new listeners to the task using an Activity scope task.addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot state) { // Success! // ... } }); } }
getActiveUploadTasks
מאחזר את כל משימות ההעלאה הפעילות ברמה של ההפניה שצוינה ומתחתיה, ולכן יכול להיות שתצטרכו לטפל בכמה משימות.
המשך העלאות אחרי הפעלה מחדש של תהליכים
אם התהליך שלכם יושבת, כל ההעלאות שמתבצעות יופסקו. עם זאת, אפשר להמשיך להעלות אחרי שהתהליך יופעל מחדש, על ידי חידוש סשן ההעלאה עם השרת. כך אפשר לחסוך זמן ורוחב פס כי ההעלאה לא מתחילה מתחילת הקובץ.
כדי לעשות זאת, מתחילים להעלות באמצעות putFile
. ב-StorageTask
, שמתקבל, קוראים ל-getUploadSessionUri
ושומרים את הערך שמתקבל באחסון מתמיד (כמו SharedPreferences).
Kotlin
uploadTask = storageRef.putFile(localFile) uploadTask.addOnProgressListener { taskSnapshot -> sessionUri = taskSnapshot.uploadSessionUri if (sessionUri != null && !saved) { saved = true // A persisted session has begun with the server. // Save this to persistent storage in case the process dies. } }
Java
uploadTask = mStorageRef.putFile(localFile); uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { Uri sessionUri = taskSnapshot.getUploadSessionUri(); if (sessionUri != null && !mSaved) { mSaved = true; // A persisted session has begun with the server. // Save this to persistent storage in case the process dies. } } });
אחרי שהתהליך מופעל מחדש עם העלאה שהופסקה, צריך להפעיל שוב את putFile. אבל הפעם צריך להעביר גם את ה-Uri שנשמר.
Kotlin
// resume the upload task from where it left off when the process died. // to do this, pass the sessionUri as the last parameter uploadTask = storageRef.putFile( localFile, storageMetadata { }, sessionUri, )
Java
//resume the upload task from where it left off when the process died. //to do this, pass the sessionUri as the last parameter uploadTask = mStorageRef.putFile(localFile, new StorageMetadata.Builder().build(), sessionUri);
הסשנים נמשכים שבוע. אם תנסו להמשיך סשן אחרי שהוא הסתיים או אם הייתה בו שגיאה, תקבלו קריאה חוזרת (callback) של כשל. באחריותכם לוודא שהקובץ לא השתנה בין ההעלאות.
טיפול בשגיאות
יכולות להיות כמה סיבות לשגיאות בהעלאה, כולל קובץ מקומי שלא קיים או משתמש שאין לו הרשאה להעלות את הקובץ הרצוי. מידע נוסף על שגיאות זמין בקטע Handle Errors במסמכים.
דוגמה מלאה
בהמשך מוצגת דוגמה מלאה להעלאה עם מעקב אחר ההתקדמות וטיפול בשגיאות:
Kotlin
// File or Blob file = Uri.fromFile(File("path/to/mountains.jpg")) // Create the file metadata metadata = storageMetadata { contentType = "image/jpeg" } // Upload file and metadata to the path 'images/mountains.jpg' uploadTask = storageRef.child("images/${file.lastPathSegment}").putFile(file, metadata) // Listen for state changes, errors, and completion of the upload. // You'll need to import com.google.firebase.storage.component1 and // com.google.firebase.storage.component2 uploadTask.addOnProgressListener { (bytesTransferred, totalByteCount) -> val progress = (100.0 * bytesTransferred) / totalByteCount Log.d(TAG, "Upload is $progress% done") }.addOnPausedListener { Log.d(TAG, "Upload is paused") }.addOnFailureListener { // Handle unsuccessful uploads }.addOnSuccessListener { // Handle successful uploads on complete // ... }
Java
// File or Blob file = Uri.fromFile(new File("path/to/mountains.jpg")); // Create the file metadata metadata = new StorageMetadata.Builder() .setContentType("image/jpeg") .build(); // Upload file and metadata to the path 'images/mountains.jpg' uploadTask = storageRef.child("images/"+file.getLastPathSegment()).putFile(file, metadata); // Listen for state changes, errors, and completion of the upload. uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount(); Log.d(TAG, "Upload is " + progress + "% done"); } }).addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() { @Override public void onPaused(UploadTask.TaskSnapshot taskSnapshot) { Log.d(TAG, "Upload is paused"); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // Handle successful uploads on complete // ... } });
אחרי שהעליתם קבצים, נלמד איך להוריד אותם מ-Cloud Storage.