     /// - Parameter bodyData: read data
     ///
     private class func parseMultipart(_ bodyData: NSMutableData, boundary: String) -> ParsedBody? {
-        guard let bodyAsString = String(data: bodyData, encoding: NSUTF8StringEncoding) else {
+        guard let boundaryData = String("--" + boundary).data(using: NSUTF8StringEncoding), let endBoundaryData = String("--" + boundary + "--").data(using: NSUTF8StringEncoding), let newLineData = "\r\n".data(using: NSUTF8StringEncoding) else {
+            Log.error("Error converting strings to data for multipart parsing")
             return nil
         }
+        
         enum ParseState {
             case preamble, body
         }
         var state = ParseState.preamble
         var parts: [Part] = []
         var currentPart = Part()
-        var data = NSMutableData()
-        // divide body by lines
-        let bodyAsStringLines = bodyAsString.components(separatedBy: NSCharacterSet.newlines()).filter({!$0.isEmpty})
+        var partData = NSMutableData()
+        let bodyLines = divideDataByNewLines(data: bodyData, newLineData: newLineData)
         // main parse loop
-        for bodyLine in bodyAsStringLines {
+        for bodyLine in bodyLines {
             switch(state) {
-            case .preamble where bodyLine.hasPrefix("--" + boundary), .body where bodyLine.hasPrefix("--" + boundary):
+            case .preamble where bodyLine.hasPrefix(boundaryData), .body where bodyLine.hasPrefix(boundaryData):
                 // boundary found
-                if data.length > 0 {
-                    if let parser = getParsingFunction(contentType: currentPart.type), let parsedBody = parser(data) {
+                if partData.length > 0 {
+                    if let parser = getParsingFunction(contentType: currentPart.type), let parsedBody = parser(partData) {
                         currentPart.body = parsedBody
                     } else {
-                        currentPart.body = .raw(data)
+                        currentPart.body = .raw(partData)
                     }
                     parts.append(currentPart)
                 }
                 currentPart = Part()
-                data = NSMutableData()
-                if bodyLine.hasPrefix("--" + boundary + "--") {
+                partData = NSMutableData()
+                if bodyLine.hasPrefix(endBoundaryData) {
                     // end boundary found, end of parsing
                     return .multipart(parts)
                 }

    }

}

                break
            case .body:
                // check if header
                if let bodyLineAsString = String(data: bodyLine, encoding: NSUTF8StringEncoding) {
                    if let labelRange = bodyLineAsString.range(of: "content-type:", options: [.anchoredSearch, .caseInsensitiveSearch], range: bodyLineAsString.startIndex..<bodyLineAsString.endIndex) {
                        currentPart.type = bodyLineAsString.substring(from: bodyLineAsString.index(after: labelRange.upperBound))
                        currentPart.headers[.type] = bodyLineAsString
                    } else if let labelRange = bodyLineAsString.range(of: "content-disposition:", options: [.anchoredSearch, .caseInsensitiveSearch], range: bodyLineAsString.startIndex..<bodyLineAsString.endIndex) {
                        if let nameRange = bodyLineAsString.range(of: "name=", options: .caseInsensitiveSearch, range: labelRange.upperBound..<bodyLineAsString.endIndex) {
                            let valueStartIndex = bodyLineAsString.index(after: nameRange.upperBound)
                            let valueEndIndex = bodyLineAsString.range(of: "\"", range: valueStartIndex..<bodyLineAsString.endIndex)
                            currentPart.name = bodyLineAsString.substring(with: valueStartIndex..<(valueEndIndex?.lowerBound ?? bodyLineAsString.endIndex))
                        }
                        currentPart.headers[.disposition] = bodyLineAsString
                    } else if bodyLineAsString.range(of: "content-transfer-encoding:", options: [.anchoredSearch, .caseInsensitiveSearch], range: bodyLineAsString.startIndex..<bodyLineAsString.endIndex) != nil {
                        //TODO: Deal with this
                        currentPart.headers[.transferEncoding] = bodyLineAsString
                    }
                    else {
                        // is data, add to data object
                        if partData.length > 0 {
                            // data is multiline, add linebreaks back in
                            partData.append(newLineData)
                        }
                        partData.append(bodyLine)
                    }
                } else {
                    // is data, add to data object
                    if partData.length > 0 {
                        // data is multiline, add linebreaks back in
                        partData.append(newLineData)
                    }
                    partData.append(bodyLine)
                }
            }
            
        }
        return nil
    }
    
    private class func divideDataByNewLines(data: NSData, newLineData: NSData) -> [NSData] {
        var dataLines = [NSData]()
        var lineStart = 0
        var currentPosition = 0
        while currentPosition < data.length - 1 {
            let newLineCanidate = data.subdata(with: NSRange(location: currentPosition, length: 2))
            if newLineCanidate.isEqual(to: newLineData) {
                dataLines.append(data.subdata(with: NSRange(location: lineStart, length: currentPosition - lineStart)))
                // skip new line characters
                currentPosition += 2
                lineStart = currentPosition
            } else {
                currentPosition += 1
            }
        }
        return dataLines
    }

    ///
