AFNetworking 使用 NSMutableURLRequest 上传?
Posted
技术标签:
【中文标题】AFNetworking 使用 NSMutableURLRequest 上传?【英文标题】:AFNetworking Upload Using NSMutableURLRequest? 【发布时间】:2014-03-31 13:03:17 【问题描述】:我正在努力学习 AFNetworking
,我从他们的 Github 中获取了样本。我不知道使用php
在dataToPost
中设置哪些参数。我是Objective-C
和php
的新手。有人可以看看我的 sn-p 和我的php
看看我缺少什么。很难找到 AFNetworking
的“上传”教程,但那里有大量的 JSON
教程。
我想使用NSMutableURLRequest
,因为最终我想从数组或UITableview
上传;到目前为止,这里是 mt 代码:
PHP:
<?php
header("Content-Type: application/json");
$uploaddir = './'; //Uploading to same directory as PHP file
$file = basename($_FILES['userfile']['name']);
$uploadFile = $file;
$randomNumber = rand(0, 99999);
$newName = $uploadDir . $randomNumber . $uploadFile;
if (!is_uploaded_file($_FILES['userfile']['tmp_name']))
$result = array("success" => false);
echo json_encode($result);
exit();
if ($_FILES['userfile']['size']> 300000)
$result = array("success" => false, "message" =>"the uploaded file is too big");
echo json_encode($result);
exit();
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $newName))
$postsize = ini_get('post_max_size'); //Not necessary, I was using these
$canupload = ini_get('file_uploads'); //server variables to see what was
$tempdir = ini_get('upload_tmp_dir'); //going wrong.
$maxsize = ini_get('upload_max_filesize');
//echo "http://localhost:8888/upload/$file" . "\r\n" . $_FILES['userfile']['size'] . "\r\n" . $_FILES['userfile']['type'] ;
$result = array("success" => true,
"code" => 0,
"message" => "success",
"postsize" => $postsize,
"canupload" => $canupload,
"tempdir" => $tempdir,
"maxsize" => $maxsize);
echo json_encode($result);
?>
Xcode:
// 1. Create AFHTTPRequestSerializer which will create your request.
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
// 2. Create an NSMutableURLRequest.
NSMutableURLRequest *request =
[serializer multipartFormRequestWithMethod:@"POST" URLString:@"http://my.com/upload/upload.php"
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
[formData appendPartWithFileData:imageData
name:@"userfile"
fileName:@"myimage.jpg"
mimeType:@"image/jpeg"];
];
// 3. Create and use AFHTTPRequestOperationManager to create an AFHTTPRequestOperation from the NSMutableURLRequest that we just created.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *operation =
[manager HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject)
NSLog(@"Success %@", responseObject);
failure:^(AFHTTPRequestOperation *operation, NSError *error)
NSLog(@"Failure %@", error.description);
];
// 4. Set the progress block of the operation.
[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
NSInteger totalBytesWritten,
NSInteger totalBytesExpectedToWrite)
NSLog(@"Wrote %ld/%ld", (long)totalBytesWritten, (long)totalBytesExpectedToWrite);
];
// 5. Begin!
[operation start];
错误(已解决):
2014-03-31 15:37:46.921 TestingUpload[7190:60b] Wrote 32768/59063
2014-03-31 15:37:46.922 TestingUpload[7190:60b] Wrote 59063/59063
2014-03-31 15:37:46.923 TestingUpload[7190:60b] Wrote 32768/59063
2014-03-31 15:37:46.923 TestingUpload[7190:60b] Wrote 59063/59063
2014-03-31 15:37:46.925 TestingUpload[7190:60b] Success
canupload = 1;
code = 0;
maxsize = 32M;
message = success;
postsize = 32M;
success = 1;
tempdir = "/Applications/MAMP/tmp/php";
2014-03-31 15:37:46.927 TestingUpload[7190:60b] Success
canupload = 1;
code = 0;
maxsize = 32M;
message = success;
postsize = 32M;
success = 1;
tempdir = "/Applications/MAMP/tmp/php";
感谢您的帮助和解释。谢谢!
【问题讨论】:
我没有测试过,但是随便看了一下,PHP看起来还不错。 检查上面。我不再关心太大了,因为它总是与设备大小相同。 如果您想小心一些恶意用户注意到文件上传的 URL 并决定将 2 GB 的文件上传到您的服务器上,那么太大的检查很重要。这就是为什么它通常在那里;以尽量减少被一些不法之徒滥用的机会。在您的测试中没什么大不了的,但在您投入生产之前,请考虑重新添加该代码(但使用 JSON 响应)。 是的,效果很好...我添加了一个 for 循环,看看我是否可以上传 2 张以上的图片,效果很好。你在说什么文件大小? @Rob 将 PHP 更新为我对 JSON/size 错误的解释。看起来怎么样? 【参考方案1】:您的 PHP 正在寻找字段名称 userfile
,但您的 Objective-C 正在使用 attachment
。您必须在两个平台上使用相同的字段名称。我还假设“<$php
”只是一个错字,而您的本意是“<?php
”。
您可能需要考虑的其他一些改进:
我建议您可能希望更改您的 PHP 以返回 JSON,而不仅仅是编写文本字符串。您的 Objective-C 代码将更容易解析响应并区分各种错误和成功。
例如,如果成功,您的 PHP 可能会执行以下操作:
$result = array("success" => true, "code" => 0, "message" => "success");
或者,如果您想记录这些附加值,就像在现有代码示例中一样,您可以:
$result = array("success" => true,
"code" => 0,
"message" => "success",
"postsize" => $postsize,
"canupload" => $canupload,
"tempdir" => $tempdir,
"maxsize" => $maxsize);
如果不成功,你可以这样做:
$result = array("success" => false, "code" => 1, "message" => "file not found");
或
$result = array("success" => false, "code" => 2, "message" => "file too large");
无论选择哪个$result
,完成后,您都应该对其进行JSON编码并echo
它(而不是回显简单的文本字符串):
echo json_encode($result);
显然,使用您想要的任何代码和消息,但想法是返回 JSON,它可以很容易地解析以确定上传请求是否成功,如果不成功,那么为什么。尝试解析来自服务器的简单文本响应本质上是脆弱的。
无论如何,您的 Objective-C 可以解析此响应并检查 success
或 code
值并适当地处理这些场景。
我不建议让 PHP 将上传文件保存在与 PHP 本身相同的文件夹中。至少,我会为上传创建一个专用子目录。我个人会选择一个完全在 Web 服务器目录结构之外的目录。
【讨论】:
感谢您回复我。我在parameters:dataToPost
中传递了什么?
谢谢!我正在考虑使用nil
,但不想贸然下结论。如果我在查询 mysql 并且需要 URL 中的“用户名”和“密码”,是否使用参数?我需要将attachment
更改为userFile
? formdata
中的 fileName
怎么样?这有关系吗?它只是一个占位符吧?
Xcode 说multipartFormRequestWithMethod
被贬值了?
我用错误和固定代码编辑了我的问题。【参考方案2】:
根据您更新的代码示例和报告的警告/错误,我有一些观察:
您收到关于 multipartFormRequestWithMethod
被弃用的消息,因为您使用的是不带 error
参数的演绎版,但它已被另一个带有此附加参数的演绎版替换。有关详细信息,请参阅AFURLRequestSerialization.h
中此方法的声明。
您关于text/html
的错误是由于PHP 发送的响应的标题报告Content-type
或text/html
。如果您的 PHP 脚本没有在您的 PHP 中发送回 JSON,您必须更改您的 Objective-C 代码,以便它知道期待一个 HTTP 响应(默认情况下,它期待返回 JSON):
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
这告诉AFHTTPRequestOperationManager
接受来自服务器的任何 HTTP 响应。
或者,如果您将 PHP 更改为返回 JSON(恕我直言,您应该这样做),您不仅需要将 PHP 代码更改为结果的 echo
和 json_encode
,还需要通知 PHP 指定适当的Content-Type
在标题中。因此,在您 echo
PHP 中的任何 JSON 之前),将以下行添加到 PHP 代码中:
header("Content-Type: application/json");
你说:
我以为内容类型是在
mimetype
中定义的
mimetype
为多部分请求的该部分定义了Content-type
。但是整个请求也有自己的Content-type
标头。该响应还在其标题中包含Content-type
设置。此错误告诉您响应包含text/html
的Content-type
,它预期application/json
。 (请参阅我之前关于修复该问题的观点。)
【讨论】:
好的,谢谢。同时,我将研究AFURLRequestSerialization.h
,并在我的答案中更新了 PHP。以上是关于AFNetworking 使用 NSMutableURLRequest 上传?的主要内容,如果未能解决你的问题,请参考以下文章
NsMutable 不是 swift 中 [anyobject] 的子类型
如何将 NSString 值设置为 NSMutable 字典?