一、AFN上传文件
// 1. 使用AFHTTPSessionManager的接口
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSDictionary *dic = @{@"businessType":@"dyz",
@"fileType":@"image",
@"file":@"img.jpeg"
};
[manager POST:@"http://114.215.186.169:9002/api/demo/test/file" parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
// 在这个block中设置需要上传的文件
NSString *path = [[NSBundle mainBundle] pathForResource:@"1" ofType:@"jpg"];
// 将本地图片数据拼接到formData中 指定name
[formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:@"file" error:nil];
//或者使用这个接口拼接 指定name和filename
NSData *picdata =[NSData dataWithContentsOfFile:path];
[formData appendPartWithFileData:picdata name:@"image" fileName:@"image.jpg" mimeType:@"image/jpeg"];
} progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"progress --- %@",uploadProgress.localizedDescription);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"responseObject-------%@", responseObject);
dispatch_async(dispatch_get_main_queue(), ^{
});
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"Error-------%@", error);
}];
二、Alamofire-多表单上传
SessionManager.default
.upload(multipartFormData: { (mutilPartData) in
mutilPartData.append("dyz".data(using: .utf8)!, withName: "name")
mutilPartData.append("IMEdyz".data(using: .utf8)!, withName: "username")
mutilPartData.append("123456".data(using: .utf8)!, withName: "PASSWORD")
//mutilPartData.append(data as! Data, withName: "fileName")
}, to: urlString) { (result) in
print(result)
switch result {
case .failure(let error):
print(error)
case .success(let upload,_,_):
upload.response(completionHandler: { (response) in
print("****:\(response) ****")
})
}
}
open func upload(
multipartFormData: @escaping (MultipartFormData) -> Void,
usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
to url: URLConvertible,
method: HTTPMethod = .post,
headers: HTTPHeaders? = nil,
queue: DispatchQueue? = nil,
encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
{
do {
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
return upload(
multipartFormData: multipartFormData,
usingThreshold: encodingMemoryThreshold,
with: urlRequest,
queue: queue,
encodingCompletion: encodingCompletion
)
} catch {
(queue ?? DispatchQueue.main).async { encodingCompletion?(.failure(error)) }
}
}
-
multipartFormData(formData)
执行外部闭包
open func upload(
multipartFormData: @escaping (MultipartFormData) -> Void,
usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
with urlRequest: URLRequestConvertible,
queue: DispatchQueue? = nil,
encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
{
DispatchQueue.global(qos: .utility).async {
let formData = MultipartFormData()
multipartFormData(formData)
var tempFileURL: URL?
do {
var urlRequestWithContentType = try urlRequest.asURLRequest()
urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
let isBackgroundSession = self.session.configuration.identifier != nil
if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession {
let data = try formData.encode()
let encodingResult = MultipartFormDataEncodingResult.success(
request: self.upload(data, with: urlRequestWithContentType),
streamingFromDisk: false,
streamFileURL: nil
)
(queue ?? DispatchQueue.main).async { encodingCompletion?(encodingResult) }
} else {
let fileManager = FileManager.default
let tempDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data")
let fileName = UUID().uuidString
let fileURL = directoryURL.appendingPathComponent(fileName)
tempFileURL = fileURL
var directoryError: Error?
// Create directory inside serial queue to ensure two threads don't do this in parallel
self.queue.sync {
do {
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
} catch {
directoryError = error
}
}
if let directoryError = directoryError { throw directoryError }
try formData.writeEncodedData(to: fileURL)
let upload = self.upload(fileURL, with: urlRequestWithContentType)
// Cleanup the temp file once the upload is complete
upload.delegate.queue.addOperation {
do {
try FileManager.default.removeItem(at: fileURL)
} catch {
// No-op
}
}
(queue ?? DispatchQueue.main).async {
let encodingResult = MultipartFormDataEncodingResult.success(
request: upload,
streamingFromDisk: true,
streamFileURL: fileURL
)
encodingCompletion?(encodingResult)
}
}
} catch {
// Cleanup the temp file in the event that the multipart form data encoding failed
if let tempFileURL = tempFileURL {
do {
try FileManager.default.removeItem(at: tempFileURL)
} catch {
// No-op
}
}
(queue ?? DispatchQueue.main).async { encodingCompletion?(.failure(error)) }
}
}
}
- 点击
self.upload(data, with: urlRequestWithContentType)
@discardableResult
open func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest {
do {
let urlRequest = try urlRequest.asURLRequest()
return upload(.data(data, urlRequest))
} catch {
return upload(nil, failedWith: error)
}
}
- 点击
upload(.data(data, urlRequest))
private func upload(_ uploadable: UploadRequest.Uploadable) -> UploadRequest {
do {
let task = try uploadable.task(session: session, adapter: adapter, queue: queue)
let upload = UploadRequest(session: session, requestTask: .upload(uploadable, task))
if case let .stream(inputStream, _) = uploadable {
upload.delegate.taskNeedNewBodyStream = { _, _ in inputStream }
}
delegate[task] = upload
if startRequestsImmediately { upload.resume() }
return upload
} catch {
return upload(uploadable, failedWith: error)
}
}
三、Alamofire-参数的拼接
- 点击
let formData = MultipartFormData() multipartFormData(formData)
中MultipartFormData()
- 1:EncodingCharacters
- 2:randomBoundary 分三种情况
- 3:闭包调用
- 4:contentHeaders + stream + length
- 5:BodyPart
- 6:bodyParts add 容器收集
struct EncodingCharacters {
static let crlf = "\r\n"
}
struct BoundaryGenerator {
enum BoundaryType {
case initial, encapsulated, final
}
static func randomBoundary() -> String {
return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random())
}
static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data {
let boundaryText: String
switch boundaryType {
case .initial:
boundaryText = "--\(boundary)\(EncodingCharacters.crlf)"
case .encapsulated:
boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)"
case .final:
boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)"
}
return boundaryText.data(using: String.Encoding.utf8, allowLossyConversion: false)!
}
}
- 点击
let data = try formData.encode()
- 整体数据 encode - data - request - session
public func encode() throws -> Data {
if let bodyPartError = bodyPartError {
throw bodyPartError
}
var encoded = Data()
bodyParts.first?.hasInitialBoundary = true
bodyParts.last?.hasFinalBoundary = true
for bodyPart in bodyParts {
let encodedData = try encode(bodyPart)
encoded.append(encodedData)
}
return encoded
}
private func encode(_ bodyPart: BodyPart) throws -> Data {
var encoded = Data()
let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
encoded.append(initialData)
let headerData = encodeHeaders(for: bodyPart)
encoded.append(headerData)
let bodyStreamData = try encodeBodyStream(for: bodyPart)
encoded.append(bodyStreamData)
if bodyPart.hasFinalBoundary {
encoded.append(finalBoundaryData())
}
return encoded
}
网友评论