我正在尝试在Swift中构建一个上传iOS应用的简单文件,但在点击上传图片按钮后,在控制台中不断收到以下内部服务器错误:
********* response = <NSHTTPURLResponse: 0x7f95284b65c0> { URL: http://website.com/upload.php } { status code: 500, headers {
Age = 0;
"Cache-Control" = "max-age=0";
Connection = "keep-alive";
"Content-Length" = 655;
"Content-Type" = "text/html; charset=iso-8859-1";
Date = "Thu, 30 Jul 2015 04:58:50 GMT";
Expires = "Thu, 30 Jul 2015 04:58:50 GMT";
"X-Cache" = MISS;
"X-Varnish" = 107809910;
} }
********* response data = <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>500 Internal Server Error</title>
</head><body>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error or
misconfiguration and was unable to complete
your request.</p>
<p>Please contact the server administrator at
no-reply@x10hosting.com to inform them of the time this error occurred,
and the actions you performed just before this error.</p>
<p>More information about this error may be available
in the server error log.</p>
<p>Additionally, a 404 Not Found
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
这是我的Swift View Controller代码:
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
@IBOutlet weak var myImageView: UIImageView!
@IBOutlet weak var myActivityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func selectPhotoPressed() {
var myPickerControl = UIImagePickerController()
myPickerControl.delegate = self
myPickerControl.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(myPickerControl, animated: true, completion: nil)
}
@IBAction func uploadImagePressed() {
myImageUploadRequest()
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
myImageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
self.dismissViewControllerAnimated(true, completion: nil)
}
func myImageUploadRequest()
{
let myURL = NSURL(string: "http://website.com/upload.php");
let request = NSMutableURLRequest(URL: myURL)
request.HTTPMethod = "POST"
let param = [
"firstName": "John",
"lastName": "Smith",
"userID": "1"
]
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = UIImageJPEGRepresentation(myImageView.image, 1)
if (imageData == nil) { return; }
request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", imageDataKey: imageData, boundary: boundary)
myActivityIndicator.startAnimating();
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
println("error=\(error)")
return
}
// print out response object
println("********* response = \(response)")
// print out response bdoy
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("********* response data = \(responseString)")
dispatch_async(dispatch_get_main_queue(), {
self.myActivityIndicator.stopAnimating()
self.myImageView.image = nil
});
}
task.resume()
}
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {
var body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("-\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
let filename = "user-profile.jpg"
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(imageDataKey)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}
}
extension NSMutableData {
func appendString(string: String) {
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
appendData(data!)
}
}
以下是后端upload.php文件:
<?php
$firstName = $_REQUEST["firstName"];
$lastName = $_REQUEST["lastName"];
$userID = $_REQUEST["userID"];
$target_dir = "uploads";
if (!file_exists($target_dir))
mkdir($target_dir, 0777, true);
$target_dir .= "/" . basename($_FILES["file"]["name"]);
if (move_uploaded_file($_FILES["files"]["tmp_name"], $target_dir)) {
echo json_encode([
"Message" => "The file " . basename($_FILES["file"]["name"]) . "has been uploaded.",
"Status" => "OK",
"userID" => $_REQUEST["userID"]
]);
} else {
echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error",
"userID" => $_REQUEST["userID"]
]);
}
?>
我不确定这里有什么问题。为了排除故障,我向upload.php添加了ini_set('display_errors', 1);
以及将文件的更改权限添加到777,但是继续在控制台中获取该消息。但是,如果我只是在浏览器中转到http://website.com/upload.php
,我会收到{"Message":"Sorry, there was an error uploading your file.","Status":"Error","userID":null}
答案 0 :(得分:2)
修复边界createBodyWithParameters
上的破折号,如下所示:
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {
let body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n") // <----- "--" Double Dash
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
let filename = "user-profile.jpg"
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n") // <----- "--" Double Dash
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(imageDataKey)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n") // <----- "--" Double Dash
return body
}