Cloud Storage cho Firebase giúp bạn nhanh chóng và dễ dàng tải tệp lên Đã cung cấp bộ chứa Cloud Storage và được Firebase quản lý.
Tải tệp lên
Để tải tệp lên Cloud Storage, trước tiên bạn phải tạo tham chiếu đến đường dẫn đầy đủ của tệp, bao gồm cả tên tệp.
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
Sau khi tạo tệp đối chiếu thích hợp, bạn hãy gọi putBytes()
,
putFile()
hoặc putStream()
để tải tệp lên
lên Cloud Storage.
Bạn không thể tải lên dữ liệu có tham chiếu đến thư mục gốc của Bộ chứa Cloud Storage. Tham chiếu của bạn phải trỏ đến một URL con.
Tải lên từ dữ liệu trong bộ nhớ
Phương thức putBytes()
là cách đơn giản nhất để tải
lên Cloud Storage. putBytes()
nhận byte[]
và trả về một
UploadTask
mà bạn có thể dùng để quản lý và theo dõi trạng thái tải lên.
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. // ... } });
Vì putBytes()
chấp nhận một byte[]
nên ứng dụng của bạn phải lưu giữ toàn bộ
nội dung của tệp trong bộ nhớ cùng một lúc. Cân nhắc sử dụng putStream()
hoặc
putFile()
để sử dụng ít bộ nhớ hơn.
Tải lên từ luồng
Phương thức putStream()
là cách linh hoạt nhất để tải
lên Cloud Storage. putStream()
lấy InputStream
rồi trả về
UploadTask
mà bạn có thể dùng để quản lý và theo dõi trạng thái tải lên.
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. // ... } });
Tải lên từ một tệp trên máy
Bạn có thể tải lên các tệp cục bộ trên thiết bị, chẳng hạn như ảnh và video từ
camera bằng phương thức putFile()
. putFile()
nhận File
và trả về một
UploadTask
mà bạn có thể dùng để quản lý và theo dõi trạng thái tải lên.
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. // ... } });
Nhận URL tải xuống
Sau khi tải tệp lên, bạn có thể nhận URL để tải tệp xuống bằng cách gọi
phương thức getDownloadUrl()
trên 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 // ... } } });
Thêm siêu dữ liệu tệp
Bạn cũng có thể thêm siêu dữ liệu khi tải tệp lên.
Siêu dữ liệu này chứa các thuộc tính siêu dữ liệu của tệp điển hình như name
, size
,
và contentType
(thường được gọi là loại MIME). Phương thức putFile()
tự động suy luận loại MIME từ tiện ích File
, nhưng bạn có thể
ghi đè loại được phát hiện tự động bằng cách chỉ định contentType
trong siêu dữ liệu. Nếu
bạn không cung cấp contentType
và Cloud Storage không thể dự đoán
mặc định từ đuôi tệp, Cloud Storage sử dụng
application/octet-stream
Xem phần Sử dụng siêu dữ liệu tệp
để biết thêm thông tin về siêu dữ liệu tệp.
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);
Quản lý tải lên
Ngoài việc bắt đầu tải lên, bạn có thể tạm dừng, tiếp tục và huỷ quá trình tải lên bằng cách sử dụng
phương thức pause()
, resume()
và cancel()
. Tạm dừng và tiếp tục sự kiện
hãy tăng các thay đổi trạng thái pause
và progress
tương ứng. Huỷ
làm cho quá trình tải lên không thành công kèm theo một lỗi cho biết rằng
quá trình tải lên đã bị huỷ.
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();
Theo dõi tiến trình tải lên
Bạn có thể thêm trình nghe để xử lý trạng thái thành công, không thành công, tiến trình hoặc tạm dừng trong tác vụ tải lên:
Kiểu người nghe | Cách sử dụng thông thường |
---|---|
OnProgressListener |
Trình nghe này được gọi định kỳ khi dữ liệu được truyền và có thể được dùng để điền chỉ báo tải lên/tải xuống. |
OnPausedListener |
Trình nghe này được gọi bất cứ khi nào tác vụ bị tạm dừng. |
OnSuccessListener |
Trình nghe này được gọi khi tác vụ đã hoàn tất thành công. |
OnFailureListener |
Trình nghe này được gọi bất cứ khi nào quá trình tải lên không thành công. Điều này có thể xảy ra do hết thời gian chờ mạng, lỗi uỷ quyền hoặc nếu bạn huỷ tác vụ. |
OnFailureListener
được gọi bằng một thực thể Exception
. Thông tin khác
trình nghe được gọi bằng đối tượng UploadTask.TaskSnapshot
.
Đối tượng này là một khung hiển thị bất biến của tác vụ tại thời điểm sự kiện xảy ra.
UploadTask.TaskSnapshot
chứa các thuộc tính sau:
Tài sản | Loại | Mô tả |
---|---|---|
getDownloadUrl |
String |
URL có thể dùng để tải đối tượng xuống. Đây là URL công khai không thể đoán được và có thể được chia sẻ với các ứng dụng khách khác. Giá trị này được điền sẵn sau khi quá trình tải lên hoàn tất. |
getError |
Exception |
Nếu tác vụ không thành công, điều này sẽ có nguyên nhân là Ngoại lệ. |
getBytesTransferred |
long |
Tổng số byte đã được truyền khi chụp ảnh chụp nhanh này. |
getTotalByteCount |
long |
Tổng số byte dự kiến sẽ được tải lên. |
getUploadSessionUri |
String |
URI có thể được dùng để tiếp tục tác vụ này thông qua một lệnh gọi khác đến putFile. |
getMetadata |
StorageMetadata |
Trước khi quá trình tải lên hoàn tất, siêu dữ liệu này sẽ được gửi đến máy chủ. Sau khi quá trình tải lên hoàn tất, đây là siêu dữ liệu được máy chủ trả về. |
getTask |
UploadTask |
Công việc đã tạo bản tổng quan nhanh này. Sử dụng tác vụ này để huỷ, tạm dừng hoặc tiếp tục quá trình tải lên. |
getStorage |
StorageReference |
StorageReference dùng để tạo UploadTask . |
Trình nghe sự kiện UploadTask
cung cấp cách thức đơn giản và hiệu quả để theo dõi
tải sự kiện lên.
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"); } });
Xử lý các thay đổi về Vòng đời hoạt động
Quá trình tải lên vẫn tiếp tục diễn ra trong nền ngay cả khi vòng đời hoạt động thay đổi (chẳng hạn như như trình bày một hộp thoại hoặc xoay màn hình). Mọi trình nghe bạn đã đính kèm cũng sẽ được đính kèm. Việc này có thể dẫn đến kết quả không mong muốn nếu được gọi sau khi dừng hoạt động.
Bạn có thể giải quyết vấn đề này bằng cách đăng ký cho người nghe thông qua phạm vi hoạt động
để tự động huỷ đăng ký chúng khi hoạt động dừng lại. Sau đó, hãy sử dụng
Phương thức getActiveUploadTasks
khi hoạt động khởi động lại để lấy các tác vụ tải lên
vẫn đang chạy hoặc mới hoàn thành gần đây.
Ví dụ bên dưới minh hoạ điều này cũng như cách duy trì bộ nhớ đường dẫn tham chiếu đã sử dụng.
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
truy xuất tất cả tác vụ tải lên đang hoạt động tại và bên dưới
cung cấp tài liệu tham khảo, nên bạn có thể phải xử lý nhiều nhiệm vụ.
Việc tiếp tục tải lên trong các quá trình khởi động lại
Nếu quy trình của bạn bị tắt, mọi quá trình tải lên đang diễn ra sẽ bị gián đoạn. Tuy nhiên, bạn có thể tiếp tục tải lên sau khi quá trình khởi động lại bằng cách tiếp tục phiên tải lên bằng máy chủ. Việc này có thể giúp tiết kiệm thời gian và băng thông bằng cách không bắt đầu tải lên từ đầu tệp.
Để thực hiện việc này, hãy bắt đầu tải lên thông qua putFile
. Trên StorageTask
thu được,
gọi getUploadSessionUri
và lưu giá trị thu được vào bộ nhớ liên tục
(chẳng hạn như 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. } } });
Sau khi quy trình khởi động lại do quá trình tải lên bị gián đoạn, hãy gọi hàm putFile một lần nữa. Nhưng lần này cũng chuyển URI đã lưu.
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);
Số phiên kéo dài một tuần. Nếu bạn cố gắng tiếp tục một phiên sau khi phiên đó hết hạn hoặc nếu gặp lỗi, bạn sẽ nhận được lệnh gọi lại không thành công. Bạn có trách nhiệm đảm bảo tệp không thay đổi giữa các lần tải lên.
Lỗi xử lý
Có một số lý do khiến lỗi có thể xảy ra khi tải lên, bao gồm tệp cục bộ không tồn tại hoặc người dùng không có quyền tải lên tệp mong muốn. Bạn có thể tìm thêm thông tin về các lỗi trong phần Xử lý lỗi của phần Tài liệu.
Ví dụ đầy đủ
Ví dụ đầy đủ về một tệp tải lên có tính năng theo dõi tiến trình và xử lý lỗi được hiển thị dưới đây:
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 // ... } });
Giờ bạn đã tải tệp lên, hãy tìm hiểu cách tải chúng xuống từ Cloud Storage.