我的目标是使用HTTP POST从PHP脚本和客户端Swift代码存储和检索原始数据。我正在使用存储MEDIUMBLOB数据的MySQL数据库。
我成功地从Swift中发送了数据并将其存储到数据库中。 这是我用于存储数据的工作代码(为简化起见,我删除了WHERE子句),我可以使用PHPMyAdmin查看存储的原始数据(例如[BLOB-345.6 KiB],其大小与客户端代码数据大小相同): / p>
<?php
//...
$file = $_FILES['file']['tmp_name'];
$file_data = file_get_contents($file);
$file_info = finfo_open(FILEINFO_MIME_TYPE);
$file_type = finfo_file($file_info, $file);
$file_size = filesize($file);
$worldMap1 = $file_data;
$query = $query = "INSERT INTO " . $this->table_name . " SET worldMap1=:worldMap1";
//...
?>
客户端Swift代码(请求结构):
let boundary = generateBoundaryString()
var request = URLRequest(url: requestedUrl)
request.httpMethod = POSTMETHOD
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpBody = createBodyWithParametersForData(
parameters: dataBody,
filePathKey: "file",
imageDataKey: data,
boundary: boundary
)
private func createBodyWithParametersForData(parameters: [String: Any]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {
var body = Data();
if parameters != nil {
for (key, value) in parameters! {
body.appendString(string: "--\(boundary)\r\n")
body.appendString(string: "Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString(string: "\(value)\r\n")
}
}
let filename = "file"
let mimetype = "application/octet-stream"
body.appendString(string: "--\(boundary)\r\n")
body.appendString(string: "Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString(string: "Content-Type: \(mimetype)\r\n\r\n")
body.append(imageDataKey)
body.appendString(string: "\r\n")
body.appendString(string: "--\(boundary)--\r\n")
return body
}
现在,我只想将数据发送回客户端Swift代码(非工作代码):
<?php
// required headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// Fetch the record:
$query = "SELECT worldMap1 FROM " . $this->table_name . "";
// prepare query
$stmt = $db->prepare($query);
//...
// execute query
$stmt->execute();
if ($stmt->rowCount() == 1) {
// Fetch the record into a variable:
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$file_size = filesize($row["worldMap1"]);
// Send the content information:
header("Content-Type: application/octet-stream\n");
header("Content-Disposition: attachment; filename=\"file\"\n");
header("Content-Length: {$file_size}\n");
// Send the file:
echo $row["worldMap1"];
}
// Omit the closing PHP tag to avoid tainting the downloaded file
在客户端,我要么收到0字节数据,要么收到超时错误代码。 我也尝试硬编码Content-Length值,例如1000。 我没有看到任何有关如何从PHP代码发送原始数据的清晰文档。 这是我发现并用于存储数据的唯一有用信息:http://www.peachpit.com/articles/article.aspx?p=1967015&seqNum=4
答案 0 :(得分:1)
通常,文件存储在目录中,而不是数据库中。
看来问题很可能与您的 {'search_default_draft_state': 1}
标头有关。我认为仅仅告诉浏览器还不够,我期待一个八位位组流。
为了让您的浏览器正确地将其识别为附件,我将更改标题以指示您正在处理的文件的实际类型,以便它知道如何解释该文件。
像这样:
Content-Type: application/octet-stream\n
以下是接受的MIME-TYPES
的列表您还将覆盖您的内容类型标头,从“必需” header('Content-Type: ' . $type);
到application/json
。我可能不会发送octet-stream
标头。即使我相信它将被后者覆盖。
在脚本输出任何内容之前,请确保已发送标题。即使是未知的空格也会引起您的问题。
我也看不到标题中需要aplication/json
。
我还考虑使用单引号而不是双引号,因为您可能会犯错误,而将文件名用双引号转义。
希望有帮助。
再次,如果是我,我不会这样做。我会将所有文件上传到目录而不是数据库。