📜  Firebase在Cloud Storage中上传文件

📅  最后修改于: 2021-01-02 03:48:40             🧑  作者: Mango

在云端存储中上传文件

云端存储为开发人员提供了方便快捷地将文件上传到由Firebase提供或管理的Google云端存储分区的功能。默认情况下,在Cloud Storage存储桶中上传文件时需要Firebase身份验证。但是我们可以修改Firebase安全规则,以允许取消身份验证访问。

由于默认引擎应用,Google应用和Firebase共享此存储桶,因此配置公共访问权限还可以使新上传的App Engine文件可以公开访问。设置身份验证时,请确保再次访问我们的存储桶。

为了将文件上传到Cloud Storage,我们将首先创建对带有文件名的文件完整路径的引用。

// 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")

//When the file names are same, the references point to different files
mountainsRef.name == mountainImagesRef.name // true
mountainsRef.path == mountainImagesRef.path // false

创建适当的引用后,我们将调用putBytes(),putFile()或putStream()方法将文件上传到Cloud Storage。我们无法参考Google Cloud Storage存储桶的根目录上传数据。我们的参考必须指向子URL。

从内存中的数据上传

putBytes()方法是最轻松地将文件上传到Cloud Storage的最简单方法。 putBytes()方法使用byte []并返回一个UploadTask ,我们可以使用它来管理和监视上载的状态。

// Getting 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 {
    // Handlling unsuccessful uploads
}.addOnSuccessListener {
    // The taskSnapshot.metadata contains file metadata such as content-type, size, etc.
    // ...
}

由于putBytes()接受byte [],因此它要求我们的应用一次将文件的全部内容保存在内存中。我们认为putStream()putFile()使用较少的内存。

从流上传

将文件上传到Cloud Storage的最灵活的方法是使用putStream()方法。此方法采用InputStream并返回一个UploadTask ,它将用于管理和监视上载的状态。

val stream = FileInputStream(File("path/to/images/mountain.jpg"))

uploadTask = mountainsRef.putStream(stream)
uploadTask.addOnFailureListener {
    // Handling unsuccessful uploads
}.addOnSuccessListener {
    // The taskSnapshot.metadata contains file metadata such as content-type, size, etc.
    // ...
}

从本地文件上传

我们可以使用putFile()方法将本地文件上传到设备上。此方法将File作为输入,并返回一个UploadTask ,我们可以使用它来管理和监视上载的状态。

var file = Uri.fromFile(File("path/to/images/rivers.jpg"))
val riversRef = storageRef.child("images/${file.lastPathSegment}")
uploadTask = riversRef.putFile(file)

// Registering observers to listen for when the download is done or if it fails
uploadTask.addOnFailureListener {
    // Handling unsuccessful uploads
}.addOnSuccessListener {
    // The taskSnapshot.metadata contains file metadata such as content-type, size, etc.
    // ...
}

上传后获取下载网址

要下载文件,需要我们有一个URL。为了获取URL,我们必须在StorageReference上调用getDownloadUrl()方法。

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 {
        // Handling failures
        // ...
    }
}

管理上传

还有一些其他可用的方法,例如pause(),resume()cancel() ,它们可用于暂停,恢复或取消上载。在暂停和恢复事件中,暂停和进度状态分别发生变化。取消上载会导致上载失败,并显示一个错误,指示上载已被取消。

uploadTask = storageRef.child("images/mountains.jpg").putFile(file)

// Pausing the upload
uploadTask.pause()

// Resuming the upload
uploadTask.resume()

// Canceling the upload
uploadTask.cancel()

完整的例子

具有进度监控和错误处理的上传示例如下:

// Getting File or Blob
file = Uri.fromFile(File("path/to/mountains.jpg"))

// Creating the file metadata
metadata = StorageMetadata.Builder()
        .setContentType("image/jpeg")
        .build()

// Uploading the file and the metadata to the path 'images/mountains.jpg'
uploadTask = storageRef.child("images/${file.lastPathSegment}").putFile(file, metadata)

// Listening for state changes, errors, and completion of the upload.
uploadTask.addOnProgressListener { taskSnapshot ->
    val progress = (100.0 * taskSnapshot.bytesTransferred) / taskSnapshot.totalByteCount
    println("Upload is $progress% done")
}.addOnPausedListener {
    println("Upload is paused")
}.addOnFailureListener {
    // Handling unsuccessful uploads
}.addOnSuccessListener {
    // Handling successful uploads on complete
    // ...
}