使用Firebase Storage的putFile()方法导致:文件“fileName”无法打开错误

时间:2016-07-17 19:31:15

标签: ios swift url firebase firebase-storage

以下是我尝试上传文件的两种方式:

1

getURLOfPhoto(assetURL: imagesDictionary[String(whichProfileImage)]! , completionHandler: { (responseURL) in          
                                    FIRStorage.storage().reference().putFile(responseURL as! URL)
                            })

2

  let assets = PHAsset.fetchAssets(withALAssetURLs: [imagesDictionary[String(whichProfileImage)] as! URL], options: nil)
            let asset = assets.firstObject
            asset?.requestContentEditingInput(with: nil, completionHandler: { (contentEditingInput, info) in
                let imageFile = contentEditingInput?.fullSizeImageURL?

                FIRStorage.storage().reference().child("test").putFile(imageFile!, metadata: nil) { (metadata, error) in
                        if let error = error {                   
                            return
                        }   
                }
            })

我收到此错误:

 Body file is unreachable: /var/mobile/Media/DCIM/100APPLE/picture.JPG        
    Error Domain=NSCocoaErrorDomain Code=257 "The file “picture.JPG” couldn’t be opened because you don’t have permission to view it."     
        UserInfo={NSURL=file:///var/mobile/Media/DCIM/100APPLE/picture.JPG, NSFilePath=/var/mobile/Media/DCIM/100APPLE/picture.JPG,     
    NSUnderlyingError=0x15da49a0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

似乎正在成功检索URL,并且仅在调用putFile()方法时才会出现错误。

有谁知道如何解决此错误或将文件(不是Data对象)上传到Firebase存储的其他方式?

提前致谢

3 个答案:

答案 0 :(得分:4)

目前Firebase存储无法使用我在问题中使用的基于PHAsset的代码检索的文件网址(或者至少根据我的经验而言) - 即使这些文件是用户的文件用相机拍摄自己的iPhone。因此,一种解决方案是将相关文件重新保存到Firebase存储API可访问的位置,然后通过将该位置的URL传入putFile()方法来上载文件。

如果您正在使用imagePickerController()方法,则可以使用此方法:

do {
   let documentsURL = FileManager.default().urlsForDirectory(.documentDirectory,
                                                                          inDomains: .userDomainMask)[0]
   let fileURL = try documentsURL.appendingPathComponent("fileName.jpg")

   let image = info[UIImagePickerControllerOriginalImage]

   try UIImageJPEGRepresentation(image as! UIImage,1.0)?.write(to: fileURL, options: [])

                    FIRStorage.storage().reference().child("exampleLocation")
                        .putFile(fileURL, metadata: nil) { (metadata, error) in
    if let error = error {
                                print("Error uploading: \(error.description)")
                                return
                            }
                       }                
                 }
         catch {
            print("error is ", error)
        }

答案 1 :(得分:1)

由于应用沙箱,我们的上传器可能没有正确的权限来访问该文件(我们对授予广泛的文件系统访问权限非常犹豫)。

我只建议将文件存储在Documents/tmp/https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html

当然,如果它来自系统资源,我们可能想重新审视这种行为。通常我只是这样做(是的,我知道它是data而不是file因此会有更糟糕的记忆行为):

  // pragma mark - UIImagePickerDelegate overrides
  func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

    // Get local image
    guard let image: UIImage = info[UIImagePickerControllerOriginalImage] as? UIImage else { return }
    let imageData = UIImagePNGRepresentation(image)!

    // Get a reference to the location where we'll store our photos
    let photosRef = storage.reference().child("chat_photos")

    // Get a reference to store the file at chat_photos/<FILENAME>
    let photoRef = photosRef.child("\(NSUUID().UUIDString).png")

    // Upload file to Firebase Storage
    let metadata = FIRStorageMetadata()
    metadata.contentType = "image/png"
    photoRef.putData(imageData, metadata: metadata).observeStatus(.Success) { (snapshot) in
      // When the image has successfully uploaded, we get it's download URL
      let text = snapshot.metadata?.downloadURL()?.absoluteString
    }

    // Clean up picker
    dismissViewControllerAnimated(true, completion: nil)
  }

答案 2 :(得分:1)

@Mike麦克唐纳,谢谢你的答案对我有用。我有完全相同的问题,并能够解决你的建议。这是我的代码:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

    guard let image: UIImage = info[UIImagePickerControllerOriginalImage] as! UIImage else { return }
    let profileImageName = "profileImageName.png"
    let imageData = UIImagePNGRepresentation(image)!
    let filePath = "\(FIRAuth.auth()!.currentUser!.uid)/\(Int(NSDate.timeIntervalSinceReferenceDate() * 1000))"

    let photoStorageRef = FIRStorage.storage().reference().child(filePath)
    let photoRef = photoStorageRef.child("\(profileImageName)")

    let metadata = FIRStorageMetadata()
    metadata.contentType = "image/png"

    photoRef.putData(imageData, metadata: metadata) { metadata, error in
        if let error = error {
            print("Error uploading:\(error.localizedDescription)")
            return
        } else {
            guard let downloadURL = metadata!.downloadURL() else { return }
            guard let downloadURLString = metadata!.downloadURL()?.absoluteString else { return }

            //do what I need to do with downloadURL
            //do what I need to do with downloadURLString
        }
    }

希望这可以帮助其他人遇到同样的问题!