简体   繁体   中英

Upload file to amazon s3 using Alamofire

I'm using Alamofire 4.0 to create a request to upload file directly to S3 Amazon.

I'm using the service from GetCloudApp . After my request Router.shared.prepareForUploadItem from an api "https://my.cl.ly/v3/items I retrieve the json like this

{
  "slug": "1h132K0z2n3G",
  "name": "Image.png",
  "url": "http://f.cl.ly",
  "uploads_remaining": 1,
  "max_upload_size": 26214400,
  "s3": {
    "AWSAccessKeyId": "AKIAJP2C6U543KJIE2GA",
    "key": "items/353u2B053p0H0D1O3w1b/${filename}",
    "policy": "eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0xMlQxMjo0MTozOFoiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJjbG91ZGFwcC5jb3BwZXIuaW8ifSxbInN0YXJ0cy13aXRoIiwiJGtleSIsIml0ZW1zLzM1M3UyQjA1M3AwSDBEMU8zdzFiLyJdLHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiJodHRwOi8vbXkuY2wuZGV2L3YzL2l0ZW1zLzFoMTMySzB6Mm4zRy9zMyJ9LHsiYWNsIjoicHVibGljLXJlYWQifSxbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwwLDI2MjE0NDAwXV19",
    "signature": "wqSVl9+fvkvtIzGfakNF+drqN0s=",
    "success_action_redirect": "http://api.cl.ly/v3/items/1h132K0z2n3G/s3",
    "acl": "public-read"
  }
}

I take these key and value as my parameter :

"AWSAccessKeyId": "AKIAJP2C6U543KJIE2GA",
"key": "items/353u2B053p0H0D1O3w1b/${filename}",
"policy": "eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0xMlQxMjo0MTozOFoiLCJjb25kaXRpb25zIjpbeyJidWNrZXQiOiJjbG91ZGFwcC5jb3BwZXIuaW8ifSxbInN0YXJ0cy13aXRoIiwiJGtleSIsIml0ZW1zLzM1M3UyQjA1M3AwSDBEMU8zdzFiLyJdLHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiJodHRwOi8vbXkuY2wuZGV2L3YzL2l0ZW1zLzFoMTMySzB6Mm4zRy9zMyJ9LHsiYWNsIjoicHVibGljLXJlYWQifSxbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwwLDI2MjE0NDAwXV19",
"signature": "wqSVl9+fvkvtIzGfakNF+drqN0s=",
"success_action_redirect": "http://api.cl.ly/v3/items/1h132K0z2n3G/s3",
"acl": "public-read"

Then I create the request to upload my file using s3 dictionary like below :

 Alamofire.upload(multipartFormData: { (multipartForm) in

  for (key, value) in parameter {

    let valueData = value.data(using: .utf8, allowLossyConversion: false)

    guard let newData = valueData else{
      return
    }

    multipartForm.append(newData, withName: key)

    print("\(key) - \(value)")
  }

  multipartForm.append(data, withName: "file")

}, to: s3.url, method : .post) { (encodingResult) in

  switch encodingResult {
  case .success(let upload, _, _):
    upload.responseJSON { response in
      debugPrint(response)
    }
  case .failure(let encodingError):
    print(encodingError)
  }
}

Finally I retrieve the response from server like this, I know it all about authentication but I really don't know what's the right way to do that.

status code: 401, headers {
"Cache-Control" = "no-cache";
Connection = "keep-alive";
"Content-Length" = 28;
"Content-Type" = "text/plain; charset=utf-8";
Date = "Sun, 08 Jan 2017 17:37:17 GMT";
Server = "nginx/1.4.6 (Ubuntu)";
Status = "401 Unauthorized";
"Www-Authenticate" = "Digest realm=\"Application\", qop=\"auth\", algorithm=MD5, nonce=\"MTQ4Mzg5NzAzNzpiYmEwN2MzZDljM2RjNDMyMGE1NzI2ODQ5MjhjMWVkNQ==\", opaque=\"9eb56ccb2e8b017ae42bdb4739690863\"";
"X-Request-Id" = 7bd77581bf677aee1b1abba21b3ad097;
"X-Runtime" = "0.004697";
"X-UA-Compatible" = "IE=Edge,chrome=1";

I try many ways but still no luck and can't make it work. I really need help. Thank in advance.

I figured out why this problem is occurred because I need to authenticate my upload request to S3 using CloudApp 's Digest authenticate after my request to CloudApp to upload new file.

I will posted my completed code below:

func uploadFileToS3(_ s3: S3, data : Data, fileName : String, mimeType : String) {

let params = s3.s3Parameter

Alamofire.upload(multipartFormData: { (multipartForm) in

  for (key, value) in params{

    multipartForm.append(value.data(using: .utf8)!, withName: key)

  }

  multipartForm.append(data, withName: "file", fileName: fileName, mimeType: mimeType)

}, to: s3.url, method : .post, headers:["Accept":"application/json"]) { (encodingResult) in

  guard let userInfor = UserDefaults.standard.dictionary(forKey: "UserInformation") else {
    return
  }

  switch encodingResult {
  case .success(let upload, _, _):
    upload.authenticate(user: userInfor["email"]! as! String, password: userInfor["password"]! as! String)

    self.progressbar.isHidden = false
    upload.uploadProgress(closure: { (progress) in

      self.progressbar.progress = Float(progress.fractionCompleted)

    })

    upload.responseJSON{ response in

      self.progressbar.isHidden = true

      let result = JSON(response.result.value!)
      let file = CloudFile(fileInformation: result)

      self.files.append(file)

      let indexPath = IndexPath(row: 0, section: 0)

      DispatchQueue.main.async {
          self.filesTableView.insertRows(at: [indexPath], with: .automatic)
      }

    }
  case .failure(let encodingError):
    print(encodingError)
  }
}

}

Noticed upload.authenticate(user: userInfor["email"]! as! String, password: userInfor["password"]! as! String) in encodingResult result completion handle, this is where you need authenticate your upload request. Alamofire will do the rest.

Hope this will help. Thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM