为什么在使用 ios 上传文件时不调用 nodejs multer 上的 onParseEnd 回调?

Why do onParseEnd callback on nodejs multer not called when using ios to upload files?

我已经使用 nodejs 实现了一个服务器,并使用 multer 来处理文件上传。

当我使用Postman上传文件时,文件上传成功,控制台日志"upload image api"也出现

然而,当我使用 Swift 从 iOS 上传文件时,虽然文件也已成功上传,但控制台日志 "upload image api" 和 "Form parsing completed" 从未出现。这意味着回调 onParseEnd 没有被调用,我想这就是它在那里冻结并且没有进入 "upload image api" 部分的原因。

为什么我使用iOS上传文件时没有调用onParseEnd?当我使用 Postman 时一切正常。

Nodejs 和 Multer:

router.post('/upload', multer({
  dest: './public/uploads/user/',
  onFileUploadStart: function (file,req,res) {
    console.log(file.originalname + ' is starting ...')
    return true;
  },
  onFileUploadComplete: function (file) {
    console.log(file.fieldname + ' uploaded to  ' + file.path)
  },
  onParseStart: function () {
    console.log('Form parsing started at: ', new Date())
  },
  onParseEnd: function (req, next) {
    console.log('Form parsing completed at: ', new Date());
    // call the next middleware
    next();
    }
}), function(req,res,next){
    console.log("upload image api");

});

iOS swift:

var session = NSURLSession.sharedSession()
    let url = NSURL(string:url)
    var request = NSMutableURLRequest(URL: url!)
    request.HTTPMethod = method
    request.setValue("Keep-Alive", forHTTPHeaderField: "Connection")
    request.setValue("Cache-Control", forHTTPHeaderField: "no-cache")

    // set Content-Type in HTTP header

    let boundaryConstant = "Boundary-\(NSUUID().UUIDString)";
    let contentType = "multipart/form-data; boundary=\(boundaryConstant)"

    request.setValue(contentType, forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    let filename = "image.jpg"
    var body = NSMutableData()
    body.appendString("--\(boundaryConstant)\r\n")
    body.appendString("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(filename)\"\r\n")
    body.appendString("Content-Type: \(dataType)\r\n\r\n")
    body.appendData(data)
    body.appendString("\r\n")
    body.appendString("--\(boundaryConstant)\r\n")
    request.HTTPBody = body

    var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        println("Response: \(response)")
        var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
        println("Body: \(strData)")
        var err: NSError?
        var statusCode : Int = (response is NSHTTPURLResponse) ? (response as! NSHTTPURLResponse).statusCode : 404

        var json : NSDictionary?
        if(statusCode == 204){
            json = NSDictionary()
        }else{
            json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
        }

        // Did the JSONObjectWithData constructor return an error? If so, log the error to the console
        if((err != nil)) {
            println(err!.localizedDescription)
            let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
            println("Error could not parse JSON: '\(jsonStr)'")
            completed(succeeded: false, data: nil, statusCode: statusCode)
        }
        else {
            // The JSONObjectWithData constructor didn't return an error. But, we should still
            // check and make sure that json has a value using optional binding.
            if let parseJSON = json {
                completed(succeeded: true, data: json, statusCode: statusCode)
                return
            }
            else {
                // Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
                println("Error could not parse JSON: \(jsonStr)")
                completed(succeeded: false, data: nil, statusCode: statusCode)
            }
        }
    })

    task.resume()

下面是上面swift代码中使用的appendString函数。

func appendString(string: String) {
    let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
    appendData(data!)
}

我用过Alamofire,问题解决了。
https://github.com/Alamofire/Alamofire

Alamofire.upload(.POST, URLString: url, multipartFormData: { multipartFormData in
        multipartFormData.appendBodyPart(data: data, name: key, fileName: "image.jpg", mimeType: "image/jpg")
        }, encodingCompletion: { encodingResult in
            switch encodingResult {
            case .Success(let upload, _, _):
                upload.responseJSON { request, response, data, error in

                    println("Response: \(response)")
                    var json = data as? NSDictionary

                    println("Body: \(json)")
                    var statusCode : Int = (response != nil) ? response!.statusCode : 404
                    completed(succeeded: true, data: json, statusCode: statusCode)

                }
            case .Failure(let encodingError):
                completed(succeeded: false, data: nil, statusCode: 404)
            }
    })

如果有人知道前面的方法不起作用的原因,请发表评论。谢谢