这是我的快速代码,可以从应用程序上传文件。
final class UploadService {
// I'm renting a remote server and the php code is on that
private let videoUploadPath = "http://myUploadPath.php"
var uploadsSession: URLSession!
var activeUploads: [URL: Upload] = [:]
func startUpload(medium: Medium) {
guard let url = URL(string: videoUploadPath) else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
let upload = Upload(medium: medium)
upload.task = self.uploadsSession.uploadTask(with: request, fromFile: medium.avUrlAsset.url)
upload.task?.resume()
upload.isUploading = true
activeUploads[upload.medium.avUrlAsset.url] = upload
}
}
请注意,我必须使用
func uploadTask(with request: URLRequest, fromFile fileURL: URL) -> URLSessionUploadTask
// Apple documentation:
Parameters
request
A URL request object that provides the URL, cache policy, request type,
and so on. The body stream and body data in this request object are ignored.
从手机上传视频,因为这是允许后台上传的唯一方法(视频通常很大,因此我必须使后台上传成为可能)。但是,此功能会丢弃所有正文数据。
这是我的PHP代码,用于接收上载的文件并将其存储在所需的位置:
$directory = "../storage/videos/";
$destination = $directory . basename($_FILES["file"]["name"]);
if (move_uploaded_file($_FILES["file"]["tmp_name"], $destination)) {
$returnArray["status"] = "200";
$returnArray["message"] = "Upload success";
echo json_encode($returnArray);
} else {
$returnArray["status"] = "300";
$returnArray["message"] = "Upload failed" . $_FILES["file"]["error"];
echo json_encode($returnArray);
return;
}
说实话,我知道它不会成功,因为我无法指定PHP代码中$_FILES["file"]["name"]
所必需的文件类型和名称。
因此,我的问题是,如何指定要上传的文件名和类型?自功能
func uploadTask(with request: URLRequest, fromFile fileURL: URL) -> URLSessionUploadTask
丢弃所有http正文数据,如我提到的那样,也许是制作包含文件类型和名称的http标头?或者,PHP是否有另一种方式来接收我刚刚上传的文件?现在,$ _FIELS完全为空。我是PHP的新手,很抱歉,如果我说的不够清楚。
另外,对于Content-Type
,我在上载图像以更改用户的个人资料图像时使用multipart/form-data
,我将图像数据与其他数据(例如uid
)附加在一起,然后附加data作为http正文中的正文数据。但是现在,我需要上传一个文件,因为根据iOS的要求,请求中的所有正文数据都将被忽略。我该怎么办?
很多日子都困扰于此,请提供帮助。非常感谢!
答案 0 :(得分:0)
有一种方法可以保留URLSession.shared.uploadTask调用并在PHP端使用原始数据。这是一个对我有用的JSON数据示例:
使用https://developer.apple.com/documentation/foundation/url_loading_system/uploading_data_to_a_website中的Swift样例代码
SWIFT端:
struct Order: Codable {
let customerId: String
let items: [String]
}
// ...
let order = Order(customerId: "12345",
items: ["Cheese pizza", "Diet soda"])
guard let uploadData = try? JSONEncoder().encode(order) else {
return
}
let url = URL(string: "https://example.com/upload.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.uploadTask(with: request, from: uploadData) { data, response, error in
if let error = error {
print ("error: \(error)")
return
}
guard let response = response as? HTTPURLResponse,
(200...299).contains(response.statusCode) else {
print ("server error")
return
}
if let mimeType = response.mimeType,
mimeType == "application/json",
let data = data,
let dataString = String(data: data, encoding: .utf8) {
print ("got data: \(dataString)")
}
}
task.resume()
PHP端:(upload.php)
<?php
header('Content-Type: application/json; charset=utf-8');
$response = array();
try {
$uploaddir = './uploads/';
$uploadfile = $uploaddir . 'test.json';
$rawdata = file_get_contents('php://input');
if (!file_put_contents($uploadfile, $rawdata)) {
throw new RuntimeException('Failed to create file.');
}
$response = array(
"status" => "success",
"error" => false,
"message" => "File created successfully"
);
echo json_encode($response);
} catch (RuntimeException $e) {
$response = array(
"status" => "error",
"error" => true,
"message" => $e->getMessage()
);
echo json_encode($response);
}
?>
这还将把二进制数据写入文件。在这种简单情况下,无需知道文件名或内容类型。对于一般情况,它可能不起作用,但是这种进行方式允许您继续使用URLSession.shared.uploadTask并避免使用HTTP Body参数。 HTH。