如何在 Firebase 中存储图像

Posted

技术标签:

【中文标题】如何在 Firebase 中存储图像【英文标题】:How to Store Image in Firebase 【发布时间】:2019-06-10 00:12:40 【问题描述】:

我正在尝试将测试图像存储在 Firebase 存储中,但它没有出现,我认为问题出在 viewDidLoad 中的完成处理程序上,但我不确定如何修复它。它应该是“photoHelper”还是其他?下面我包含了处理 imagePicker 的“MyProfileViewController”和两个服务函数“创建图像”和“上传图像”。

import UIKit
import AVFoundation
import Photos

 class MyProfileViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate 

@IBOutlet weak var profileButton: UIButton!

let photoHelper = MGPhotoHelper()

var imagePicker: UIImagePickerController!

override func viewDidLoad() 
    super.viewDidLoad()
    profileButton.layer.cornerRadius = 0.5 * profileButton.bounds.size.width
    profileButton.clipsToBounds = true

    photoHelper.completionHandler =  image in
        ProfileService.createImage(for: image)
    


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()


@IBAction func addPhoto(_ sender: UIButton) 
    let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
    imagePicker = UIImagePickerController()
    imagePicker.delegate = self

    if (UIImagePickerController.isSourceTypeAvailable(.camera))
    
        let cameraAction = UIAlertAction(title: "Use Camera", style: .default)  (action) in

            let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)

            if (status == .authorized)
                self.DisplayPicker(type: .camera)
            
            if (status == .restricted)
                self.HandleRestricted()
            
            if (status == .denied)
                self.HandleDenied()
            
            if (status == .notDetermined)
                AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler:  (granted) in
                    if (granted)
                        self.DisplayPicker(type: .camera)
                    
                )
            
        
         alertController.addAction(cameraAction)
    

    if (UIImagePickerController.isSourceTypeAvailable(.photoLibrary)) 
        let photoLibraryAction = UIAlertAction(title: "Use Photo Library", style: .default)  (action) in

            let status = phphotoLibrary.authorizationStatus()

            if (status == .authorized)
                self.DisplayPicker(type: .photoLibrary)
            
            if (status == .restricted)
                self.HandleRestricted()
            
            if (status == .denied)
                self.HandleDenied()
            
            if (status == .notDetermined)
                PHPhotoLibrary.requestAuthorization( (status) in
                    if (status == PHAuthorizationStatus.authorized)
                        self.DisplayPicker(type: .photoLibrary)
                    
                )
            
        
        alertController.addAction(photoLibraryAction)
    

    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    alertController.addAction(cancelAction)

    alertController.popoverPresentationController?.sourceView = self.profileButton
    alertController.popoverPresentationController?.sourceRect = self.profileButton.bounds

    present(alertController, animated: true, completion: nil)


func HandleDenied()
    let alertController = UIAlertController(title: "Media Access Denied", message: "CameraTutorial does not access to your device's media. Please update your settings", preferredStyle: .alert)
    let settingsAction = UIAlertAction(title: "Go to Settings", style: .default) (action) in
        DispatchQueue.main.async 
            UIApplication.shared.open(NSURL(string: UIApplication.openSettingsURLString)! as URL)
        
    
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    alertController.popoverPresentationController?.sourceView = self.profileButton
    alertController.popoverPresentationController?.sourceRect = self.profileButton.bounds

    alertController.addAction(settingsAction)
    alertController.addAction(cancelAction)
    present(alertController, animated: true, completion: nil)


func HandleRestricted()
    let alertController = UIAlertController(title: "Media Access Denied", message: "This device is restricited from accessing any media at this time", preferredStyle: .alert)
    let defaultAction = UIAlertAction(title: "Ok", style: .default, handler: nil)

    alertController.popoverPresentationController?.sourceView = self.profileButton
    alertController.popoverPresentationController?.sourceRect = self.profileButton.bounds

    alertController.addAction(defaultAction)
    present(alertController, animated: true, completion: nil)


func DisplayPicker(type: UIImagePickerController.SourceType)
    self.imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: type)!
    self.imagePicker.sourceType = type
    self.imagePicker.allowsEditing = true

    DispatchQueue.main.async 
        self.present(self.imagePicker, animated: true, completion: nil)
    


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) 
    let chosenImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage
    profileButton.imageView?.contentMode = .scaleAspectFill
    profileButton.setImage(chosenImage, for: .normal)

    dismiss(animated: true, completion: nil)


创建图像函数

static func createImage(for image: UIImage) 
    let imageRef = Storage.storage().reference().child("test_image.jpg")
    StorageService.uploadImage(image, at: imageRef)  (downloadURL) in
        guard let downloadURL = downloadURL else 
            return
        

        let urlString = downloadURL.absoluteString
        print("image url: \(urlString)")
    

上传图片功能

static func uploadImage(_ image: UIImage, at reference: StorageReference, completion: @escaping (URL?) -> Void) 
    // 1
    guard let imageData = image.jpegData(compressionQuality: 0.1) else 
        return completion(nil)
    

    // 2
    reference.putData(imageData, metadata: nil, completion:  (metadata, error) in
        // 3
        if let error = error 
            assertionFailure(error.localizedDescription)
            return completion(nil)
        

        // 4
        reference.downloadURL(completion:  (url, error) in
            if let error = error 
                assertionFailure(error.localizedDescription)
                return completion(nil)
            
            completion(url)
        )
    )

【问题讨论】:

【参考方案1】:

首先启用规则,如果你还没有。

service firebase.storage 
  match /b/bucket/o 
    match /allPaths=** 
      allow read, write: if true;
    
  

用于上传和图像到 Firebase 存储的代码。

private void uploadImage() 

if(filePath != null)
 
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Uploading...");
progressDialog.show();

StorageReference ref = storageReference.child("images/"+ UUID.randomUUID().toString());
ref.putFile(filePath)
        .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() 
          @Override
          public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) 
            progressDialog.dismiss();
            Toast.makeText(MainActivity.this, "Uploaded", Toast.LENGTH_SHORT).show();
          
        )
        .addOnFailureListener(new OnFailureListener() 
          @Override
          public void onFailure(@NonNull Exception e) 
            progressDialog.dismiss();
            Toast.makeText(MainActivity.this, "Failed "+e.getMessage(), Toast.LENGTH_SHORT).show();
          
        )
        .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() 
          @Override
          public void onProgress(UploadTask.TaskSnapshot taskSnapshot) 
            double progress = (100.0*taskSnapshot.getBytesTransferred()/taskSnapshot
                    .getTotalByteCount());
            progressDialog.setMessage("Uploaded "+(int)progress+"%");
          
        );
 

这里 Filepath 是图像的 Uri。希望它有所帮助。

【讨论】:

以上是关于如何在 Firebase 中存储图像的主要内容,如果未能解决你的问题,请参考以下文章

如何通过云函数将图像存储在 Firebase 存储中

如何将图像上传到firebase存储然后将图像url存储在firestore中?

如何从 Firebase 存储中下载图像并将其存储在颤动的列表中 [关闭]

如何在来自 Firebase 存储的片段 ImageView 中显示图像

如何在反应js中显示来自firebase存储的所有图像

如何在单个事务中将图像上传到 Firebase 存储并在数据库中保存参考?