gpt4 book ai didi

从 iOS App (Swift) 请求时 PHP 没有响应

转载 作者:行者123 更新时间:2023-11-28 13:50:32 28 4
gpt4 key购买 nike

我在我的 iOS 应用程序中用 Swift 4 编写了一个简单的 HTTP POST 请求。

Swift代码如下:

let url = URL(string: "http://example.com/api.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"

let boundary = "Boundary-\(NSUUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

let body = NSMutableData()

// Text parameter: Action
body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Disposition: form-data; name=\"action\"\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: ("my_action" as NSString)).data(using: String.Encoding.utf8.rawValue)!)

// Text parameter: Peer ID
body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Disposition: form-data; name=\"peerid\"\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: ("123456" as NSString)).data(using: String.Encoding.utf8.rawValue)!)

// Image
body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format:"Content-Disposition: form-data; name=\"secret_img\"; filename=\"secret.jpg\"\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(imageData!)
body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)

request.httpBody = body as Data

let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {
return
}

guard let data = data else {
return
}

do {
// create json object from response Json data
/*if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print(json)
// handle json...
}*/

// Debug: check the response string
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(responseString)")
} catch let error {
print(error.localizedDescription)
}
})
task.resume()

PHP 响应空字符串(没有错误报告)。然后,我使用一个简单的 HTML 表单来测试 PHP 脚本是否可以。这是 form.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test Upload Form</title>
</head>

<body>
<form action="index.php" method="post" enctype="multipart/form-data">
<input type="hidden" name="action" value="my_action" />
<input type="hidden" name="peerid" value="123456" />
<p>Image: <input type="file" name="secret_img" required /></p>
<p><input type="submit" name="submit" id="submit" /></p>
</form>
</body>
</html>

PHP 响应:

{"status": "OK"}

证明脚本没有问题。 PHP 脚本如下,非常简单:

<?php
header('Content-Type: application/json');
if(!isset($_FILES['secret_img'])) {
echo json_encode(array('error' => 'missing image'));
exit;
}
$file = $_FILES['secret_img'];
$upload_folder = 'upload/';
if(move_uploaded_file($_FILES['secret_img']['tmp_name'], $upload_folder . $_POST['peerid'] . '_' . time() . '_' . rand(1000, 999999) . '.jpg')) {
// success
echo json_encode(array('status' => 'OK'));
} else {
echo json_encode(array('error' => 'unable to copy image'));
}
?>

我将错误缩小到 Swift 代码。我删除了 body 中的内容(注释掉 body.append() 行),然后 PHP 响应:

{"error": "missing image"}

这是正常行为。

你们能帮我找出问题所在吗?谢谢。


更新 如果我在 request.httpBody 行之前添加以下两行,dump() 返回 nil。怎么回事?

let debug = NSString(data: body as Data, encoding: String.Encoding.utf8.rawValue)
dump(debug)

body 变量已正确初始化,数据已正确附加。

最佳答案

这个问题很微妙,不容易发现。问题原因是:

  • 边界设置不正确
  • 一些更改行 \r\n 丢失/重复

要纠正这个问题,httpBody 必须更改为以下内容:

let body = NSMutableData()

// Text parameter: Action
body.append(NSString(format: "--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Disposition: form-data; name=\"action\"\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "my_action\r\n").data(using: String.Encoding.utf8.rawValue)!)

在第一个 block 中,第一个 \r\n 不是必需的(这导致 httpBody 中出现空行),并且(与格式对齐) ,第二个 block 的第一个\r\n被移动到my_action字符串的尾部。

// Text parameter: Peer ID
body.append(NSString(format: "--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Disposition: form-data; name=\"peerid\"\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "123456\r\n").data(using: String.Encoding.utf8.rawValue)!)

和第一 block 一样,\r\n重新排列(与403 Forbidden问题无关)。还简化了一些代码。

// Image
body.append(NSString(format: "--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format:"Content-Disposition: form-data; name=\"secret_img\"; filename=\"secret.jpg\"\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(imageData!)
body.append(NSString(format: "\r\n--%@--\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)

request.httpBody = body as Data

最后一个 block 有问题,导致 403 Forbidden 错误。最后一行错过了结束边界符号。

结果内容如下:

--boundary
Content-Disposition: form-data; name="action"
my_action

--boundary
Content-Disposition: form-data; name="peerid"
123456

--boundary
Content-Disposition: form-data; name="secret_img"; filename="secret.jpg"
{image data here}

--boundary--

结论:缺少结束边界导致 403 Forbidden(格式错误的 HTTP 正文)。

修复的灵感来自 MDN 上的 Content-Disposition 文档: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

关于从 iOS App (Swift) 请求时 PHP 没有响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54683965/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com