Multiple File Upload in Swift - swift

I am trying to upload multiple file to the server by my iPhone. The problem is that when I try to upload 1.4 mb file it could not upload properly. I checked the uploaded file and the file size is 1 kb. So I made this code based on the postman. As you know the postman can create the code according to which language do you want. Thank you.
function uploadFile(){
var parameters: [[String: Any]] = []
var fileCount: Int = 0
let homeDirectory = ""
var soundPath = "\(homeDirectory)\(CommonUtil.PATH_SOUND)"
soundPath = soundPath.replacingOccurrences(of: "file:///", with: "")
//fiels[0] = ["fileName" : "2021_10_19_09_12_52.wav"]
//fiels[1] = ["fileName" : "2021_10_19_09_12_53.wav"]
//fiels[3] = ["fileName" : "2021_10_19_09_12_54.wav"]
for item in files{
var dict = item as! [String:String]
let strFilePath = "\(soundPath)\(dict["fileName"]!)"
if FileManager.default.fileExists(atPath: strFilePath){
var dict = [String:Any]()
dict.updateValue("strFileName[\(fileCount)]", forKey: "key")
dict.updateValue(strFilePath, forKey: "src")
dict.updateValue("file", forKey: "type")
parameters.append(dict)
fileCount++
}
print(dict["fileName"]!)
}
var dict = [String:Any]()
dict.updateValue("strApiName", forKey: "key")
dict.updateValue("soundFileUpload", forKey: "value")
dict.updateValue("text", forKey: "type")
parameters.append(dict)
uploadFiles(parameters: parameters)
}
func uploadFiles(parameters: [[String: Any]]){
var semaphore = DispatchSemaphore(value: 0)
let boundary = "Boundary - \(UUID().uuidString)"
var body = ""
var error: Error? = nil
for param in parameters {
if param["disabled"] == nil {
let paramName = param["key"]!
body += "--\(boundary)\r\n"
body += "Content-Disposition:form-data; name=\"\(paramName)\""
if param["contentType"] != nil {
body += "\r\nContent-Type: \(param["contentType"] as! String)"
}
let paramType = param["type"] as! String
if paramType == "text" {
let paramValue = param["value"] as! String
body += "\r\n\r\n\(paramValue)\r\n"
} else {
let paramSrc = param["src"] as! String
//let fileData = URL(string: paramSrc)?.dataRepresentation ?? Data()
let fileData = try! NSData(contentsOfFile:paramSrc, options:[]) as Data
let fileContent = String(data: fileData, encoding: .utf8)
body += "; filename=\"\("file:///"+paramSrc)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
}
}
}
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)
var request = URLRequest(url: URL(string: "http://api.polytus.com/")!,timeoutInterval: Double.infinity)
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
DispatchQueue.main.async {
self.showLoading(show: false)
self.showBluetoothAlert(message: "failed")
}
print(String(describing: error))
semaphore.signal()
return
}
DispatchQueue.main.async {
self.showLoading(show: false)
self.showBluetoothAlert(message: "success")
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
}

For what I've understand you want to know the file size in the server filesystem. If this is you want you have to use an API that give you back the data, after the file is uploaded and moved from temporary web server space to final location. In brief you need to do 2 request, one for upload and one for getting the file data (space or any other data needed), or develop an API that give you as answer of the correct upload the file size.

Related

Why is this URLSession.datatask not working in Swift 5 for macos

I am trying to make my own DynamicIP updater as a command line tool so I can set it up to run as a launch agent. I thought this would be a pretty simple thing to do, but I am not getting anything when I run this bit of code.
main.swift:
import AppKit
let userName = "yourUserName"
let password = "yourPassword"
let domain = "yourDomainName"
let ftp = "ftp"
let www = "www"
let checkIPURL = URL(string: "https://svc.joker.com/nic/checkip")
let domainUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(domain)")
let ftpUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(ftp).\(domain)")
let wwwUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(www).\(domain)")
var ipAddress = ""
if let url = checkIPURL {
print("1 - \(url)")
var request = URLRequest(url: url)
print("2 - \(request.url!)")
request.httpMethod = "POST"
print("3")
let session = URLSession.shared
print("4")
session.dataTask(with: request) { data, response, error in
print("4.1")
guard error == nil else {
print("Error:", error ?? "")
return
}
print("4.2")
guard (response as? HTTPURLResponse)?
.statusCode == 200 else {
print("down")
return
}
print("4.3")
if let data = data {
if let dataString = String(decoding: data, as: UTF8.self).removeHtmlTags() {
if let startIndex = dataString.lastIndex(of: " ") {
let chars = dataString.distance(from: startIndex, to: dataString.endIndex)-1
ipAddress = String(dataString.suffix(chars))
}
}
print(ipAddress)
} else {
print("No data")
}
print("up - \(response!)")
}.resume()
print("Done.")
}
extension String {
// Credit - Andrew - https://stackoverflow.com/questions/25983558/stripping-out-html-tags-from-a-string
func removeHtmlTags() -> String? {
do {
guard let data = self.data(using: .utf8) else {
return nil
}
let attributed = try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
return attributed.string
} catch {
return nil
}
}
}
Everything outside of the session prints, but nothing inside of it prints (4.x statements).
I deleted the AppSandbox because when I have AppSandbox as a Capability and turn on Outgoing Connections I get a crash with EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
But even with AppSandbox deleted it does not work.
The strange thing is this works fine in a playground (with a slight modification turning the String extension into a function within the playground), which really makes this a head scratcher for me.
Here's my playground code:
import AppKit
let userName = "yourUserName"
let password = "yourPassword"
let domain = "yourDomainName"
let ftp = "ftp"
let www = "www"
let checkIPURL = URL(string: "https://svc.joker.com/nic/checkip")
let domainUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(domain)")
let ftpUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(ftp).\(domain)")
let wwwUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(www).\(domain)")
var ipAddress = ""
if let url = checkIPURL {
print("1 - \(url)")
var request = URLRequest(url: url)
print("2 - \(request.url!)")
request.httpMethod = "POST"
print("3")
let session = URLSession.shared
print("4")
session.dataTask(with: request) { data, response, error in
print("4.1")
guard error == nil else {
print("Error:", error ?? "")
return
}
print("4.2")
guard (response as? HTTPURLResponse)?
.statusCode == 200 else {
print("down")
return
}
print("4.3")
if let data = data {
//if let dataString = String(decoding: data, as: UTF8.self).removeHtmlTags() {
if let dataString = removeHtmlTags(data: data) {
if let startIndex = dataString.lastIndex(of: " ") {
let chars = dataString.distance(from: startIndex, to: dataString.endIndex)-1
ipAddress = String(dataString.suffix(chars))
}
}
print(ipAddress)
} else {
print("No data")
}
print("up - \(response!)")
}.resume()
print("Done.")
}
func removeHtmlTags(data: Data) -> String? {
do {
let attributed = try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
return attributed.string
} catch {
return nil
}
}
Is there something else I need to do to get this to work within the command line tool app I am trying to build?

How to send or upload image file with patch method on JSON server? swift

I want to send file of image on server when I edit choose image button, but I don't know why my image profile didn't update on sever , here is my console debugger area when app run :
and also I have this message from server that "please upload an image"
this response should change to "your profile photo updated" and also this my code :
func imageInput(asset : String) {
let semaphore = DispatchSemaphore (value: 0)
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + asset
let parameters = [
[
"key": "image",
"src": "\(path)",
"type": "file"
]] as [[String : Any]]
let boundary = "Boundary-\(UUID().uuidString)"
var body = ""
var error: Error? = nil
for param in parameters {
if param["disabled"] == nil {
let paramName = param["key"]!
print("params image key is \(paramName)")
body += "--\(boundary)\r\n"
body += "Content-Disposition:form-data; name=\"\(paramName)\""
if param["contentType"] != nil {
body += "\r\nContent-Type: \(param["contentType"] as! String)"
}
let paramType = param["type"] as! String
if paramType == "text" {
let paramValue = param["value"] as! String
print("value of param is \(paramValue)")
body += "\r\n\r\n\(paramValue)\r\n"
} else {
if path != nil {
body += "; filename=\"\(path)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n \(path)\r\n"
print("this is going to true")
}
}
}
}
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)
var request = URLRequest(url: URL(string: "https://api.offernews.co/api/user")!,timeoutInterval: Double.infinity)
request.addValue("baerar \(profileKeychain["token"]!)", forHTTPHeaderField: "Authorization")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "PATCH"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data
else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
}
and also this is my another question like this that every code that you want on this link Photo did not update when I patch it to json server swift
thanks guys

How to make a url post request which is returned by the function in Swift

Hi guys I am trying to contact my Rest API and get the data. I am successful in doing that but I want the function to return the string that it obtained.
This is why code so far:
private func getPost(one: String, two: String, link: String) {
let url = URL(string: link)!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let parameters: [String: Any] = [
"parent" : one,
"original": two
]
request.httpBody = parameters.percentEncoded()
var responseString = ""
print("Sarcasm \(yourMessage) \(otherMessage) \(link)")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
error == nil else { // check for fundamental networking error
print("error", error ?? "Unknown error")
return
}
guard (200 ... 299) ~= response.statusCode else { // check for http errors
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
responseString = String(data: data, encoding: .utf8)!
print("responseString = \(responseString)")
// return responseString
}
task.resume()
}
Where :
extension Dictionary {
func percentEncoded() -> Data? {
return map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]#" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
All I want is this function (getPost) to return the response string that it obtains from the post request. However, I do not know what to do. I mean the application gets the response string from the post request but then I want to modify the function so that it returns it instead of printing it.

Logical fault in repeat-while loop?

I have a problem with the repeat-while loop.I dont know why it doesnt work at my code.Maybe i have some logical fault.
func getJson(){
repeat{
movieName.isHidden = true
let randomNumber = Int(arc4random_uniform(128188))
let jsonUrlString = "https://api.url/3/movie/" + String(randomNumber) + "?api_key="
//let jsonUrlString = "https://api.url.org/3/movie/564?api_key=key&language=de-DE"
guard let url = URL(string: jsonUrlString) else
{return}
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else {return}
let dataString = String(data: data, encoding: .utf8)
print(dataString ?? String())
strTrue = false
Here I'm checking if the api returns some data if not they will give me a status code 34.Im checking for the word "status code".
If the api returns "status_code". I'm checking it with a if and then I turn string-code to true.So the condition of the repeat-while loop is
then string-code is true he will start it again and looking for a new movie id.But I tested it and it doesn't work. Maybe you guys can help me :)
let stringCode = dataString?.contains("status_code")
if stringCode == true {
print("yes fehler 34")
strTrue = stringCode!
print(strTrue)
}
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] else {return}
let movie = Movie(json: json)
print(movie.name)
print(movie.genres)
let imageString = "https://image.url.org/t/p/w500"+(movie.imageUrl)
let url2 = URL(string: imageString)
//self.movieImage.downloadedFrom(url: url2!)
self.movieDescriptionLabel = movie.overview
self.movieNameLabel = movie.name
DispatchQueue.main.async {
self.movieName.isHidden = false
self.movieName.text = self.movieNameLabel
self.movieDescription.text = self.movieDescriptionLabel
self.movieImage.downloadedFrom(url: url2!)
}
} catch let jsonError {
print("Error",jsonError)
self.getJson()
}
}.resume()
}while(strTrue == true)

Displaying JSON data nicely in Swift 3

I'm quite new to swift and I'm trying to display JSON data received from a server in 3 columns, however, I'd like the text to line up and possibly remove the brackets surrounding each bit of text. I've attached an image below, along with my code.
let u = UserDefaults.standard.value(forKey: "userIP")!
var request = URLRequest(url: URL(string: "http://\(u):3000/logs")!)
request.httpMethod = "POST"
let postString = "LockID=\(lockid)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
DispatchQueue.main.async() {
self.displayMyAlertMessage("response = \(response)")
}
}
let responseString = String(data: data, encoding: .utf8)
// print("responseString = \(responseString)")
if let data = responseString?.data(using: String.Encoding.utf8) {
let resString = JSON(data: data)
if resString["success"].stringValue == "true"
{
// save the data to be manipulated and stored in table somehow
let returned_name = resString["message"].arrayValue.map({$0["name"].stringValue})
let returned_time = resString["message"].arrayValue.map({$0["lockTime"].stringValue})
let returned_type = resString["message"].arrayValue.map({$0["type"].stringValue})
DispatchQueue.main.async() {
self.updatename!.text = "\(returned_name.description)"
self.updateLock!.text = " \(returned_type.description)"
self.updateText!.text = " \(returned_time.description)"
}
}
else if resString["success"].stringValue == "false"
{
DispatchQueue.main.async() {
self.displayMyAlertMessage(resString["message"].stringValue)
}
}
Im maniplulating the JSON data with SwiftyJSON. Any ideas on how i can strip out the [""]?
Cheers
returned_name and the other returned... variables is an array of strings caused by the map function. Printing an array using the description method displays "[item1, item2, item3]". To print each string separately you need a repeat loop.
let returnedArray = resString["message"].arrayValue // you might cast the object to `[[String:Any]]`
for item in returnedArray {
print(item["name"])
print(item["lockTime"])
print(item["type"])
}
To display the values in a table view you need a model, the best way is a custom struct
struct Item {
let name : String
let lockTime : String
let type : String
}
Then create a data source array
var items : [Item]()
And map your received JSON to the model
let returnedArray = resString["message"].arrayValue
for item in returnedArray {
let name = item["name"] ?? ""
let lockTime = item["lockTime"] ?? ""
let type = item["type"] ?? ""
items.append(Item(name:name, lockTime:lockTime, type:type))
}
Put the code to parse the JSON in viewDidLoad and call reloadData() at the end, in cellForRow get the item for the row from the array and display the values for example:
let item = items[indexPath.row]
self.updatename!.text = item.name
self.updateLock!.text = item.lockTime
self.updateText!.text = item.type
PS: since you are new to Swift don't use snake case variable names (returned_name), use camel case (returnedName).