I’m currently working on an iOS app in Swift that involves uploading images to a server. The image uploading works fine for most images, but I’ve noticed that when I take a photo directly from the iPhone camera and try to upload it, the image appears black on the server.
Here’s the code I’m using to handle the image uploading:
func stripMetaData(from image: UIImage) -> UIImage? {
guard let cgImage = image.cgImage else { return nil }
let strippedImage = UIImage(cgImage: cgImage, scale: image.scale, orientation: image.imageOrientation)
return strippedImage
}
func publishData() {
isLoading = true
guard let uiImage = selectedImage?.asUIImage() else { return }
guard let strippedImage = stripMetaData(from: uiImage) else { return }
guard let imageData = strippedImage.jpegData(compressionQuality: 1.0) else { return }
uploadImage(imageData: imageData)
}
func uploadImage(imageData: Data) {
let url = URL(string: "https://cloud.ellicode.com/mobile/upload_file.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
let boundary = UUID().uuidString
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let parameters: [String: Any] = [
"SECRET_KEY": "05fe5e2d-8878-4ba6-9bfc-ccc4498eb219",
"type": assetType,
"name": assetName,
"description": assetDesc,
"price" : assetPrice,
"userID" : UserID
]
let dataBody = createDataBody(withParameters: parameters, media: [(data: imageData, mimeType: "image/jpeg", filename: "image.jpg")], boundary: boundary, fileKey: assetType)
request.httpBody = dataBody
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
isLoading = false
} else if let data = data {
let str = String(data: data, encoding: .utf8)
print("Received data:\n\(str ?? "")")
print("Request Headers: \(request.allHTTPHeaderFields ?? [:])")
if let bodyString = String(data: dataBody, encoding: .utf8) {
print("Request Body: \(bodyString)")
}
isLoading = false
newsheet = false
}
}
task.resume()
}
func createDataBody(withParameters parameters: [String: Any], media: [(data: Data, mimeType: String, filename: String)], boundary: String, fileKey: String) -> Data {
let lineBreak = "\r\n"
var body = Data()
for (key, value) in parameters {
body.append("--\(boundary)\(lineBreak)".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"\(key)\"\(lineBreak)\(lineBreak)".data(using: .utf8)!)
body.append("\(value)\(lineBreak)".data(using: .utf8)!)
}
for item in media {
body.append("--\(boundary)\(lineBreak)".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"\(fileKey)\"; filename=\"\(item.filename)\"\(lineBreak)".data(using: .utf8)!)
body.append("Content-Type: \(item.mimeType)\(lineBreak)\(lineBreak)".data(using: .utf8)!)
body.append(item.data)
body.append(lineBreak.data(using: .utf8)!)
}
body.append("--\(boundary)--\(lineBreak)".data(using: .utf8)!)
return body
}
func loadAssets() {
// API endpoint URL
let apiUrl = URL(string: "https://cloud.ellicode.com/mobile/all_assets.php")!
// Prepare the request
var request = URLRequest(url: apiUrl)
request.httpMethod = "POST"
// Set the request body data
let parameters: [String: String] = [
"SECRET_KEY": "05fe5e2d-8878-4ba6-9bfc-ccc4498eb219",
]
request.httpBody = parameters
.map { "\($0)=\($1)" }
.joined(separator: "&")
.data(using: .utf8)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
// Create a URLSession task
URLSession.shared.dataTask(with: request) { data, response, error in
if let httpResponse = response as? HTTPURLResponse {
print("HTTP Status Code: \(httpResponse.statusCode)")
}
if let data = data {
do {
// Decode the response
let decoder = JSONDecoder()
let apiResponse = try decoder.decode(ContentResponse.self, from: data)
// Handle the decoded response
DispatchQueue.main.async {
assets = []
apiResponse.Data.forEach { data in
switch data {
case .content(let content):
assets.append(content)
case .string(let errorMessage):
// Handle String
print("Error: \(errorMessage)")
// Show an alert or handle the error as needed
alert = true
alertText = errorMessage
case .message(_):
alert = true
alertText = "Undefined content type"
}
}
}
} catch {
print("Error decoding response: \(error)")
alert = true
alertText = "Failed to decode response."
}
} else if let error = error {
print("Error: \(error.localizedDescription)")
alert = true
alertText = "Failed to fetch data from the server."
}
}.resume()
}
I’ve tried several things to debug this issue:
- Checked the image before upload: The image appears fine on the device before it’s uploaded.
- Checked the server-side script: The server-side script seems to be working fine as it correctly processes and stores other images.
- Printed the server response: The server response doesn’t indicate any issues with the image upload.
- Checked the HTTP status code: The status code returned from the server is 200, indicating that the request was successful.
I’ve also tried correcting the image orientation before converting it to data, and stripping the metadata from the image, but neither of these solutions resolved the issue.
Has anyone else encountered this issue or have any suggestions on what else I could try?




