nodejs を使用してサーバーを実装し、ファイルのアップロードを処理するために multer を使用しました。
Postman を使用してファイルをアップロードすると、ファイルが正常にアップロードされ、コンソール ログ "upload image api" も表示されます。
ただし、Swift を使用して iOS からファイルをアップロードすると、ファイルも正常にアップロードされますが、コンソール ログ「アップロード イメージ API」と「フォーム解析が完了しました」は表示されません。これは、コールバック onParseEnd が呼び出されないことを意味します。これが、そこでフリーズし、「画像 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 迅速:
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()
以下は、上記の迅速なコードで使用される appendString 関数です。
func appendString(string: String) {
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
appendData(data!)
}