我有一个像这样的上传表单:
<form action="http://localhost/upload.php" method="post" enctype="multipart/form-data">
<input type="file" id="upload" name="upload" />
</form>
和php代码继续上传表单:
isset($_FILES["upload"]) or die("Error");
// Path prepare stuff
if (move_uploaded_file($_FILES["upload"]["tmp_name"], $outputFile)) {
// Other processing stuffs
}
在xcode中,我构建了这样的请求:
NSMutableURLRequest* request = [[AFHTTPRequestSerializer serializer]
multipartFormRequestWithMethod:@"POST"
URLString:@"http://localhost/upload.php"
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
[formData appendPartWithFormData:data name:@"somefilename.ext"];
} error:nil];
但好像我做错了,对吧?
更新
我是AFNetworking的新手,我想了解它如何像上面那样构建多重/表格数据。看起来代码缺少输入的名称&#34; upload&#34;因此将无法通过php上传脚本的第一行。我从AFNetworking的GitHub上阅读了该文档,但他们没有提及使用NSData构建表单数据的情况。
答案 0 :(得分:13)
好吧,在 AFNetworking 3.0 您可以通过这种方式上传多种形式的零件数据,Check this
AFNetworking 3.0是AFNetworking的最新主要版本,3.0删除了对现已弃用的基于NSURLConnection的API的所有支持。如果您的项目以前使用过这些API,建议您现在升级到基于NSURLSession的API。本指南将引导您完成该过程。
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://localhost/upload.php" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:data name:@"uploadFile" fileName:@"somefilename.txt" mimeType:@"text/plain"] // you file to upload
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
dispatch_async(dispatch_get_main_queue(), ^{
//Update the progress view
[progressView setProgress:uploadProgress.fractionCompleted];
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"%@ %@", response, responseObject);
}
}];
[uploadTask resume];
答案 1 :(得分:2)
AFNetworking doc关于多部分,请说明您应该使用:
[[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST"......
然后使用NSURLSessionUploadTask
作为resume
方法(链接中的完整代码)。
我无法使用,而是使用了AFHTTPSessionManager:
AFHTTPSessionManager *manager = [AFHTTPSessionManager alloc]initWithBaseURL: @"someURL..."];
// If you need to add few more headers, now is the time - if not you can skip this
[manager setRequestSerializer:[AFJSONRequestSerializer serializer]];
[[manager requestSerializer] setValue:@"your custom value"
forHTTPHeaderField:@"relevant key"];
// Setting basic auth - only if you need it
[[manager requestSerializer] setAuthorizationHeaderFieldWithUsername:@"username"
password:@"password"];
[manager POST:@"appendedPath"
parameters:params
constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
[formData appendPartWithFileData:yourNSDataFile
name:@"file"
fileName:@"customFileName"
// The server I was working on had no type but you can google for all the existing types
mimeType:@""];
}
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (responseObject != nil)
{
NSDictionary *jsonDictionary = responseObject;
}
}
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
// Handle your error
}];
答案 2 :(得分:1)
如果你有一个大文件,你绝不想这样做,因为它需要将整个文件加载到内存中。这是一种将文件从磁盘流式传输到HTTP请求的方法,这样您的内存使用率仍然很低。谢谢你原来的答案!它就像一个魅力。
NSInputStream *fileInputStream = [[NSInputStream alloc] initWithFileAtPath:filePath];
if (!fileInputStream) {
NSLog(Error, @"Could not get a fileInputStream from the file path");
return;
}
NSError *error;
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"PUT" URLString:fullUrlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithInputStream:fileInputStream name:@"uniqueIdentifier" fileName:@"filename" length:<lengthOfFileLong>];
} error:&error];
if (error) {
NSLog(Error, @"Error creating multipart form upload request: %@", [error userInfo]);
completionHandler(nil, error);
}
[request setAllHTTPHeaderFields:headerDictionary];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
NSLog(Debug, @"Cloud Upload Completion: %f", uploadProgress.fractionCompleted);
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@", [error userInfo]);
completionHandler(nil, error);
} else {
NSLog(@"Success: %@ %@", response, responseObject);
}
}];
[uploadTask resume];