I want to download file from azure with REST API and I written below code for iOS Swift >3, but when I run the download task, get this error:
InvalidHeaderValue
The value for one of the HTTP headers is not in the correct format.
RequestId:10d9c8f8-001a-00db-283c-1ab1d1000000
Time:2017-08-21T05:14:18.2768791Zx-ms-version
private let account = "myAccount"
private let key = "My key is encrypted as base64"
private let fileName = "My file name which have to download"
private let SHARE_NAME = "My share name"
let date = Date().currentTimeZoneDate() + " GMT"
func downloadFileFromAzure(fileName:String)
{
// Create destination URL
let documentsUrl:URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
let destinationFileUrl = documentsUrl.appendingPathComponent(fileName)
//Create URL to the source file you want to download
let fileURL = URL(string: "https://\(account).file.core.windows.net/\(SHARE_NAME)/\(fileName)")!
//create session
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
//create headers field
var request = URLRequest(url:fileURL)
request.setValue(date,forHTTPHeaderField: "x-ms-date")
request.setValue("2014-02-14", forHTTPHeaderField: "x-ms-version")
request.setValue("\(getFileRequest(account:account, fileName: fileName))", forHTTPHeaderField: "Authorization")
//download files
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
print("tempLocalUrl: \(tempLocalUrl)")
print("destinationFileUrl: \(destinationFileUrl)")
//reading
do {
let text = try String(contentsOf: destinationFileUrl, encoding: String.Encoding.utf8)
print("reading files data : \(text)")
}
catch (let writeError){
print("Error reading a file \(writeError)")
}
} catch (let writeError) {
print("Error creating a file \(destinationFileUrl) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: %@", error?.localizedDescription);
}
}
task.resume()
}
public func getFileRequest(account:String,fileName:String)->String
{
let canonicalizedResources = "/\(account)/\(SHARE_NAME)/\(fileName)"
let canonicalizedHeaders = "x-ms-date:\(date)\nx-ms-version:2014-02-14"
let stringToSign = "GET\n\n\n\n\n\n\n\n\n\n\n\n\(canonicalizedHeaders)\n\(canonicalizedResources)"
let auth = getAuthenticationString(stringToSign:stringToSign);
return auth
}
///getAuthenticationString
public func getAuthenticationString(stringToSign:String)->String
{
let authKey: String = stringToSign.hmac(algorithm: HMACAlgorithm.SHA256, key: key)
let auth = "SharedKey " + account + ":" + authKey;
return auth;
}
enum HMACAlgorithm {
case MD5, SHA1, SHA224, SHA256, SHA384, SHA512;
func toCCHmacAlgorithm() -> CCHmacAlgorithm {
var result: Int = 0
switch self {
case .MD5:
result = kCCHmacAlgMD5
case .SHA1:
result = kCCHmacAlgSHA1
case .SHA224:
result = kCCHmacAlgSHA224
case .SHA256:
result = kCCHmacAlgSHA256
case .SHA384:
result = kCCHmacAlgSHA384
case .SHA512:
result = kCCHmacAlgSHA512
}
return CCHmacAlgorithm(result)
}
func digestLength() -> Int {
var result: CInt = 0
switch self {
case .MD5:
result = CC_MD5_DIGEST_LENGTH
case .SHA1:
result = CC_SHA1_DIGEST_LENGTH
case .SHA224:
result = CC_SHA224_DIGEST_LENGTH
case .SHA256:
result = CC_SHA256_DIGEST_LENGTH
case .SHA384:
result = CC_SHA384_DIGEST_LENGTH
case .SHA512:
result = CC_SHA512_DIGEST_LENGTH
}
return Int(result)
}
}
extension String {
func hmac(algorithm: HMACAlgorithm, key: String) -> String {
let keyBytes = key.base64DecodeAsData()
let dataBytes = self.cString(using: String.Encoding.utf8)
var result = [CUnsignedChar](repeating: 0, count: Int(algorithm.digestLength()))
CCHmac(algorithm.toCCHmacAlgorithm(), keyBytes.bytes, keyBytes.length, dataBytes!, Int(strlen(dataBytes!)), &result)
let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength())))
let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength76Characters)
return String(hmacBase64)
}
func base64DecodeAsData() -> NSData {
let decodedData = NSData(base64Encoded: self, options: NSData.Base64DecodingOptions(rawValue: 0))
return decodedData!
}
Edit:
I only get this error in the Xcode.
InvalidHeaderValue
The value for one of the HTTP headers is not in the correct format.
RequestId:10d9c8f8-001a-00db-283c-1ab1d1000000
Time:2017-08-21T05:14:18.2768791Zx-ms-version
But when I tried sharedKey(which is generated in ios) in the android source get this error:
AuthenticationFailed
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.equestId:379c5c1b-001a-0017-1a19-1bd564000000ime:2017-08-22T07:38:04.8712051ZThe MAC signature found in the HTTP request 'tJcl9LyzF2BzlZMdW9ULtMojDamn9HnEY9LulpDOsYg=' is not the same as any computed signature. Server used following string to sign: 'GETx-ms-date:Tue, 22 Aug 2017 07:32:52 GMT-ms-version:2014-02-14account/SHARE_NAME/fileName'.
error
variable do you get more details or only the one you posted? – Gaurav Mantri