Skip to content

Commit

Permalink
Add Qiniu upload function
Browse files Browse the repository at this point in the history
  • Loading branch information
LeeCenY committed Jul 24, 2018
1 parent 7ec11c8 commit 4891d69
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 0 deletions.
25 changes: 25 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "PerfectQiniu",
products: [
.library(
name: "PerfectQiniu",
targets: ["PerfectQiniu"]),
],
dependencies: [
.package(url: "https://github.com/PerfectlySoft/Perfect-CURL.git", from: "3.0.6"),
.package(url: "https://github.com/PerfectlySoft/Perfect-Crypto.git", from: "3.1.2"),
],
targets: [
.target(
name: "PerfectQiniu",
dependencies: ["PerfectCURL", "PerfectCrypto"]),
.testTarget(
name: "PerfectQiniuTests",
dependencies: ["PerfectQiniu"]),
]
)
96 changes: 96 additions & 0 deletions Sources/PerfectQiniu/Qiniu.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// Qiniu.swift
// COpenSSL
//
// Created by nil on 2018/4/26.
//

import Foundation
import PerfectCrypto
import PerfectCURL
import cURL

/// 七牛配置
public struct QiniuConfiguration {

let accessKey: String
let secretKey: String
let scope: String
let fixedZone: QNFixedZone
let DEBUG: Bool

public enum QNFixedZone: String {
case HDzone = "https://up.qiniup.com"
case HBzone = "https://up-z1.qiniup.com"
case HNzone = "https://up-z2.qiniup.com"
case BMzone = "https://up-na0.qiniup.com"
case DNYzone = "https://up-as0.qiniup.com"
}

public init(accessKey: String, secretKey: String, scope: String, fixedZone: QNFixedZone = QNFixedZone.HDzone, DEBUG: Bool = false) {
self.accessKey = accessKey
self.secretKey = secretKey
self.scope = scope
self.fixedZone = fixedZone
self.DEBUG = DEBUG
}
}

//七牛操作
public class Qiniu {

struct PutPolicy: Codable {
let scope: String
let deadline: Int
}

func getToken(config: QiniuConfiguration) throws -> String? {

let deadline = Date().timeIntervalSince1970 + 36500
let putPolicy = PutPolicy.init(scope: config.scope, deadline: Int(deadline))

let jsonData = try JSONEncoder().encode(putPolicy)
let base64String = jsonData.base64EncodedString().urlSafeBase64()

guard let encodeData = base64String.sign(Digest.sha1, key: HMACKey.init(config.secretKey)),
let encodeBase64 = encodeData.encode(.base64),
let encodeString = String.init(validatingUTF8: encodeBase64) else {
return nil
}

let encodedSignString = encodeString.urlSafeBase64()
return "\(config.accessKey):\(encodedSignString):\(base64String)"
}

public static func upload(fileName: String = "?", file: String, config: QiniuConfiguration) throws -> [String:Any] {

guard let token = try Qiniu().getToken(config: config) else {
return ["error": "bad token"]
}

let fields = CURL.POSTFields()
let _ = fields.append(key: "token", value: token)
let _ = fields.append(key: "key", value: fileName)
let _ = fields.append(key: "file", path: file)

let curl = CURL(url: config.fixedZone.rawValue)
let ret = curl.formAddPost(fields: fields)
defer { curl.close() }
guard ret.rawValue == 0 else {
return ["error": curl.strError(code: ret)]
}
let _ = curl.setOption(CURLOPT_VERBOSE, int: config.DEBUG ? 1 : 0 )
let r = curl.performFullySync()

var ptr = r.bodyBytes
ptr.append(0)
let s = String(cString: ptr)
return try s.jsonDecode() as? [String:Any] ?? [:]
}
}

public extension String {
func urlSafeBase64() -> String {
return self.replacingOccurrences(of: "+", with: "_").self.replacingOccurrences(of: "/", with: "_")
}
}
7 changes: 7 additions & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import XCTest

import PerfectQiniuTests

var tests = [XCTestCaseEntry]()
tests += PerfectQiniuTests.allTests()
XCTMain(tests)
15 changes: 15 additions & 0 deletions Tests/PerfectQiniuTests/PerfectQiniuTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import XCTest
@testable import PerfectQiniu

final class PerfectQiniuTests: XCTestCase {
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
XCTAssertEqual(PerfectQiniu().text, "Hello, World!")
}

static var allTests = [
("testExample", testExample),
]
}
9 changes: 9 additions & 0 deletions Tests/PerfectQiniuTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import XCTest

#if !os(macOS)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(PerfectQiniuTests.allTests),
]
}
#endif

0 comments on commit 4891d69

Please sign in to comment.