php - iOS Swift 5 - 通过调用 PHP 函数将文件上传到服务器
问题描述
我正在尝试将文件(在这种情况下我正在尝试使用图像,但我需要能够上传任何类型的文件,尤其是视频文件)到我的服务器。
这是我的 PHP 代码,它在服务器端运行良好:
<?php include '_config.php';
if ($_FILES["file"]["error"] > 0) {
echo "Error: " .$_FILES["file"]["error"]. "<br>";
} else {
// Check file size
if ($_FILES["file"]["size"] > 20485760) { // 20 MB
echo "ERROR: Your file is larger than 20 MB. Please upload a smaller one.";
} else { uploadImage(); }
}// ./ If
// UPLOAD IMAGE ------------------------------------------
function uploadImage() {
// generate a unique random string
$randomStr = generateRandomString();
$filePath = "uploads/".$randomStr;
// upload image into the 'uploads' folder
move_uploaded_file($_FILES['file']['tmp_name'], $filePath);
// echo the link of the uploaded image
echo $filePath;
}
// GENERATE A RANDOM STRING ---------------------------------------
function generateRandomString() {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i<20; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString."_".$_POST['fileName'];
}
?>
这是我的 Swift 5 函数:
func uploadFile(_ aImage:UIImage, maxWidth:CGFloat, completion: @escaping (_ fileURL:String?) -> Void) {
showHUD()
let image = scaleImageToMaxWidth(image: aImage, newWidth: maxWidth)
// Generate a random filename
var filename = ""
for _ in 0..<20 {
let randomChar = Int(arc4random() % UInt32(charsForRand.count))
filename += charsForRand[randomChar]
}
filename += "__image.jpg"
print("FILENAME: \(filename)")
let boundary = UUID().uuidString
let fieldName = "reqtype"
let fieldValue = "fileupload"
let fieldName2 = "userhash"
let fieldValue2 = "caa3dce4fcb36cfdf9258ad9c"
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
var urlRequest = URLRequest(url: URL(string: DATABASE_PATH + "upload-file.php")!)
urlRequest.httpMethod = "POST"
urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var data = Data()
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(fieldName)\"\r\n\r\n".data(using: .utf8)!)
data.append("\(fieldValue)".data(using: .utf8)!)
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(fieldName2)\"\r\n\r\n".data(using: .utf8)!)
data.append("\(fieldValue2)".data(using: .utf8)!)
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"fileToUpload\"; fileName=\"\(filename)\"\r\n".data(using: .utf8)!)
data.append("Content-Type: image/png\r\n\r\n".data(using: .utf8)!)
data.append(image.jpegData(compressionQuality: 1.0)!)
data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
// Send a POST request to the URL, with the data we created earlier
session.uploadTask(with: urlRequest, from: data, completionHandler: { responseData, response, error in
if error != nil { print("\(error!.localizedDescription)") }
guard let responseData = responseData else {
DispatchQueue.main.async {
self.simpleAlert("Something went wrong while uploading, try again.")
}
completion(nil)
return
}
if let response = String(data: responseData, encoding: .utf8) {
completion("\(DATABASE_PATH)\(response)")
print("UPLOAD URL: \(DATABASE_PATH)\(response)")
}
}).resume()
}
我在 ViewController 中调用该函数如下:
uploadFile(UIImage(named: "default_avatar")!, maxWidth: 300) { (fileURL) in
if fileURL != nil {
print("FILE URL: \(fileURL!)")
}
}
但这是我在 Xcode 控制台中得到的:
FILE URL: https://example.com/uploads/8iWQOrwr0wgNDor8XNhX_
UPLOAD URL: https://example.com/uploads/8iWQOrwr0wgNDor8XNhX_
这意味着我的函数不会将“__image.jpg”字符串附加到filename
变量中,它也不会将我的图像上传到我服务器上的上传文件夹。
我究竟做错了什么?如果我从输入类型为file的表单调用我的 PHP 脚本,它就像一个魅力。所以我的 PHP 脚本很好,所以我肯定在 Swift 函数中做错了什么。
解决方案
我找到了一个解决方案,这是我编辑的 Swift 5 函数,它现在也可以接受mp4
视频文件,而不仅仅是jpg
或png
图像:
func uploadFile(fileData:Data, fileName:String , completion: @escaping (_ fileURL:String?, _ error:String?) -> Void) {
print("FILENAME: \(fileName)")
let boundary: String = "------VohpleBoundary4QuqLuM1cE5lMwCy"
let contentType: String = "multipart/form-data; boundary=\(boundary)"
let request = NSMutableURLRequest()
request.url = URL(string: DATABASE_PATH + "upload-file.php")
request.httpShouldHandleCookies = false
request.timeoutInterval = 60
request.httpMethod = "POST"
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
let body = NSMutableData()
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"fileName\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("\(fileName)\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"file\"\r\n".data(using: String.Encoding.utf8)!)
// File is an image
if fileName.hasSuffix(".jpg") {
body.append("Content-Type:image/png\r\n\r\n".data(using: String.Encoding.utf8)!)
// File is a video
} else if fileName.hasSuffix(".mp4") {
body.append("Content-Type:video/mp4\r\n\r\n".data(using: String.Encoding.utf8)!)
}
body.append(fileData)
body.append("\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
request.httpBody = body as Data
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard let _:Data = data as Data?, let _:URLResponse = response, error == nil else {
DispatchQueue.main.async { completion(nil, error!.localizedDescription) }
return
}
if let response = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) {
print("XSUploadFile -> RESPONSE: " + DATABASE_PATH + response)
DispatchQueue.main.async { completion(DATABASE_PATH + response, nil) }
// NO response
} else { DispatchQueue.main.async { completion(nil, E_401) } }// ./ If response
}; task.resume()
}
这是我使用该功能的方式:
let imageData = UIImage(named: "my_img")!.jpegData(compressionQuality: 1)
uploadFile(fileData: imageData!, fileName: "image.jpg") { (fileURL, e) in
if e == nil {
print("FILE URL: " + fileURL!)
}}
这 100% 有效。
推荐阅读
- javascript - 每 x 分钟/小时重置计时器
- maven - 覆盖默认的 maven 依赖解析行为
- javascript - 同时从 2 个选择框中删除相同的选项
- sql - Activerecord 将具有相同列值的行合并为一个
- vba - 基于另一个工作表的自动填充动态范围
- excel - 以编程方式添加没有 VBE 或 VBIDE 的 VBA 项目引用..?
- indexing - Terraform列表元素超出范围?
- javascript - Vue:传递给 vm.$nextTick 的函数何时执行?
- java - Java字节数组压缩
- python - 如何在字符之前获取所有内容并在之后获取 x 数量?