Cloud Storage for Firebase ช่วยให้คุณอัปโหลดไฟล์ไปยังที่เก็บข้อมูล Cloud Storage ที่ Firebase มีให้และจัดการได้อย่างรวดเร็วและง่ายดาย
อัปโหลดไฟล์
หากต้องการอัปโหลดไฟล์ไปยัง Cloud Storage ก่อนอื่นคุณต้องสร้างการอ้างอิงไปยังเส้นทางแบบเต็มของไฟล์ รวมถึงชื่อไฟล์
Kotlin+KTX
// 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+KTX
// 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+KTX
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+KTX
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+KTX
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+KTX
// 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+KTX
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 |
ระบบจะเรียกใช้ Listener นี้เป็นระยะๆ เมื่อมีการโอนข้อมูล และสามารถใช้เพื่อแสดงตัวบ่งชี้การอัปโหลด/ดาวน์โหลด |
OnPausedListener |
ระบบจะเรียกใช้ Listener นี้ทุกครั้งที่งานหยุดชั่วคราว |
OnSuccessListener |
ระบบจะเรียก Listener นี้เมื่องานเสร็จสมบูรณ์แล้ว |
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 |
งานที่สร้างสแนปชอตนี้ ใช้งานนี้เพื่อยกเลิก หยุดชั่วคราว หรืออัปโหลดต่อ |
getStorage |
StorageReference |
StorageReference ที่ใช้สร้าง UploadTask |
Listener เหตุการณ์ UploadTask
เป็นวิธีที่ง่ายและมีประสิทธิภาพในการตรวจสอบเหตุการณ์การอัปโหลด
Kotlin+KTX
// 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"); } });
จัดการการเปลี่ยนแปลงวงจรชีวิตของกิจกรรม
การอัปโหลดจะยังคงดำเนินต่อไปในเบื้องหลังแม้ว่าวงจรกิจกรรมจะเปลี่ยนแปลง (เช่น การแสดงกล่องโต้ตอบหรือการหมุนหน้าจอ) ผู้ฟังที่คุณแนบไว้ จะยังแนบมาด้วย ซึ่งอาจทำให้เกิดผลลัพธ์ที่ไม่คาดคิดหากมีการเรียกใช้ หลังจากกิจกรรมหยุดลงแล้ว
คุณสามารถแก้ปัญหานี้ได้โดยการติดตาม Listener ด้วยขอบเขตกิจกรรมเพื่อยกเลิกการลงทะเบียนโดยอัตโนมัติเมื่อกิจกรรมหยุดลง จากนั้นใช้เมธอด getActiveUploadTasks
เมื่อกิจกรรมเริ่มต้นใหม่เพื่อรับงานอัปโหลดที่ยังทำงานอยู่หรือเพิ่งทำเสร็จ
ตัวอย่างด้านล่างแสดงให้เห็นวิธีดังกล่าว และยังแสดงวิธีคงเส้นทางอ้างอิงของพื้นที่เก็บข้อมูลที่ใช้เอาไว้ด้วย
Kotlin+KTX
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+KTX
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+KTX
// 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);
เซสชันมีอายุ 1 สัปดาห์ หากพยายามกลับมาดำเนินการในเซสชันต่อหลังจากเซสชันหมดอายุหรือเกิดข้อผิดพลาด คุณจะได้รับแบ็กคอลแจ้งความล้มเหลว คุณมีหน้าที่รับผิดชอบในการตรวจสอบว่าไฟล์ไม่มีการเปลี่ยนแปลงระหว่างการอัปโหลด
การจัดการข้อผิดพลาด
การเกิดข้อผิดพลาดขึ้นในการอัปโหลดมีสาเหตุหลายประการ ได้แก่ การที่ไฟล์ในเครื่องไม่มีอยู่ หรือผู้ใช้ไม่มีสิทธิ์อัปโหลดไฟล์ที่ต้องการ ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อผิดพลาดได้ในส่วนจัดการข้อผิดพลาดของเอกสาร
ตัวอย่างแบบเต็ม
ตัวอย่างการอัปโหลดแบบสมบูรณ์ที่มีการตรวจสอบความคืบหน้าและการจัดการข้อผิดพลาดแสดงอยู่ด้านล่าง
Kotlin+KTX
// 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