问题描述
我在multipart/form-data
上阅读了很多主题.它仍然不起作用.我可以使用URLSession.shared.uploadTask
将文件上传到服务器.
I've read quite a lot of topics here on multipart/form-data
. It still doesn't work. I am able to upload a file to my server with URLSession.shared.uploadTask
.
class MainViewController: UIViewController {
@IBOutlet weak var pictureView: UIImageView!
@IBAction func postTapped(_ sender: UIButton) {
postData()
}
func postData() {
var request = URLRequest(url: URL(string: "http://www.mywebsite.com/upload.php")!)
request.httpMethod = "POST"
request.timeoutInterval = 30.0
guard let imageData = UIImagePNGRepresentation(pictureView.image!) else {
print("oops")
return
}
let uuid = UUID().uuidString
let CRLF = "\r\n"
let filename = uuid + ".png" // file name
let formName = uuid + ".png" // file name in the form
let type = "image/png" // file type
let titleData = "hoge" // title
let titleName = uuid + ".png" // title name in the form
let boundary = String(format: "----iOSURLSessionBoundary.%08x%08x", arc4random(), arc4random())
var body = Data()
// form data //
body.append(("--\(boundary)" + CRLF).data(using: .utf8)!)
body.append(("Content-Disposition: form-data; name=\"\(titleName)\"" + CRLF + CRLF).data(using: .utf8)!)
body.append(titleData.data(using: .utf8)!)
body.append(CRLF.data(using: .utf8)!)
// file data //
body.append(("--\(boundary)" + CRLF).data(using: .utf8)!)
body.append(("Content-Disposition: form-data; name=\"\(formName)\"; filename=\"\(filename)\"" + CRLF).data(using: .utf8)!)
body.append(("Content-Type: \(type)" + CRLF + CRLF).data(using: .utf8)!)
body.append(imageData)
body.append(CRLF.data(using: .utf8)!)
// footer //
body.append(("--\(boundary)--" + CRLF).data(using: .utf8)!)
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.setValue("\(body.count)", forHTTPHeaderField: "Content-Length")
request.httpBody = body
let session = URLSession(configuration: .default)
session.dataTask(with: request) { (data, response, error) in
if let error = error {
print(error)
}
if let respose = response {
print(respose)
}
}
.resume()
}
}
PHP(索引处为upload.php)
PHP (upload.php at index)
$dir = __DIR__ . '/upload/';
$path = $dir . basename($_FILES['filename']['name']);
$data['result'] = 'failure';
if (move_uploaded_file($_FILES['filename']['tmp_name'], $path)) {
chmod($path, 0777);
$data['result'] = date("H:i:s") . ' ' . $_POST['title'] . ' success';
}
header('Content-Type: application/json');
echo json_encode($data);
上面的代码是我尝试过的许多版本之一.没有错响应显示状态码为200.但是服务器中没有文件.我不知道为什么它不起作用?与App Transport Security Settings
无关.我还没有准备好使用Alamofire. Muchos Thankos.
The code above is one of many versions I have tried. There's no error. The response says the status code is 200. But there's no file in the server. I wonder why it doesn't work? It's not about App Transport Security Settings
. I'm not ready to use Alamofire, yet. Muchos thankos.
推荐答案
我调试了您的代码,进行了简化,为清晰起见,将调试语句保留了下来.这是我想出的:
I debugged your code, simplified and left the debug statements in for clarity. Here is what I came up with:
func postData() {
var request = URLRequest(url: URL(string: "http://localhost/uploadimages/uploadtry.php")!)
request.httpMethod = "POST"
request.timeoutInterval = 30.0
guard let imageData = UIImagePNGRepresentation(pictureView.image!) else {
print("oops")
return
}
let CRLF = "\r\n"
let filename = "user.png"
let formName = "file"
let type = "image/png" // file type
let boundary = String(format: "----iOSURLSessionBoundary.%08x%08x", arc4random(), arc4random())
var body = Data()
// file data //
body.append(("--\(boundary)" + CRLF).data(using: .utf8)!)
body.append(("Content-Disposition: form-data; name=\"\(formName)\"; filename=\"\(filename)\"" + CRLF).data(using: .utf8)!)
body.append(("Content-Type: \(type)" + CRLF + CRLF).data(using: .utf8)!)
body.append(imageData as Data)
body.append(CRLF.data(using: .utf8)!)
// footer //
body.append(("--\(boundary)--" + CRLF).data(using: .utf8)!)
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
//TW debug the body data.
let theString:NSString = NSString(data: body as Data, encoding: String.Encoding.ascii.rawValue)!
print(theString)
request.setValue("\(body.count)", forHTTPHeaderField: "Content-Length")
request.httpBody = body
let session = URLSession(configuration: .default)
session.dataTask(with: request) { (data, response, error) in
if let error = error {
print(error)
}
if let respose = response {
print(respose)
}
// TW
if let data = data {
// This gives us same as server log
// You can print out response object
print("******* response = \(String(describing: response))")
print(data.count)
// you can use data here
// Print out reponse body
let responseString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
print("****** response data = \(responseString!)")
}
}
.resume()
}
提到的uploadtry.php
The mentioned uploadtry.php
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
$dir = 'media';
$path = $dir . "/" . basename($_FILES['file']['name']);
$data['result'] = 'failure';
if (move_uploaded_file($_FILES['file']['tmp_name'], $path)) {
chmod($path, 0777);
$data['result'] = ' success';
}
header('Content-Type: application/json');
echo json_encode($data);
?>
基本上,我在服务器上看到了这样的错误:
Basically I saw errors like this on the server:
Undefined index: filename in /pathtoserver/uploadimages/uploadtry.php on line 6
因此服务器无法理解您消息中的文件名.如果您没有服务器访问权限,则调试语句可帮助您在客户端查看错误.
So the server could not understand filename in your message.The debug statements help you to see the error also on the client side if you have no server access.
希望可以帮助您入门.
这篇关于无法将包含多部分/表单数据的图片上传到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!