php - 文件上传应用程序从 PHP 文件返回内部服务器错误

标签 php ios swift

我正在尝试在 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"]
    ]);
}
?>

我不确定这里出了什么问题。为了进行故障排除,我将 ini_set('display_errors', 1); 添加到 upload.php 并将文件的权限更改为 777,但继续在控制台中收到该消息。但是,如果我只是在浏览器中访问 http://website.com/upload.php,我会收到 {"Message":"Sorry,上传您的文件时出错。 ","Status":"Error","userID":null}

最佳答案

修复 Boundary 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
    }

关于php - 文件上传应用程序从 PHP 文件返回内部服务器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31715744/

相关文章:

php - Chrome 和 Firefox 处理 JavaScript/HTML 的方式不同

php - 使用 Dropbox 公共(public)链接将视频上传到 YouTube?

ios - iOS 中的 Stripe 集成 - 您没有提供 API key ?

swift - CloudKit 查询操作仅返回 300 个结果

swift - 如何在切换 View Controller 后保持 iCloud(CloudKit) 中的数据加载

php - 如何将 mysql NOW() 函数从数组传递到清理值

当 .zip >= 4GB 时,PHP 的原生 ZipArchive 类会失败。怎么修?

javascript - 使用 node.js 的 Phonegap

ios - 如何控制 iOS 上 NSLog 消息的错误级别?

objective-c - FacebookUtils 显示多个警告