SWIFT2 + Alamofire3 Upload photo, simple method - swift2

I am trying to upload photo to server with this method from alamo doc
let fileURL = NSBundle.mainBundle().URLForResource("Default", withExtension: "png")
Alamofire.upload(.POST, "https://httpbin.org/post", file: fileURL)
I edit method to my needs like this
let fileURL = NSBundle.mainBundle().URLForResource(filePath, withExtension: "png")
Alamofire.upload(.POST, urlDomain + "api/user/", parameters: parameters, headers: headers, file: fileURL)
What am I missing? I just wanna to sent 1 photo to server. Nothin more.

I found an answer on SO that I've update to Alamofire 3:
//
// FileUploader.swift
//
// Copyright (c) 2015 Narciso Cerezo Jiménez. All rights reserved.
// Largely based on this stackoverflow question: http://stackoverflow.com/questions/26121827/uploading-file-with-parameters-using-alamofire/28467829//
import Foundation
import Alamofire
private struct FileUploadInfo {
var name:String
var mimeType:String
var fileName:String
var url:NSURL?
var data:NSData?
init( name: String, withFileURL url: NSURL, withMimeType mimeType: String? = nil ) {
self.name = name
self.url = url
self.fileName = name
self.mimeType = "application/octet-stream"
if mimeType != nil {
self.mimeType = mimeType!
}
if let _name = url.lastPathComponent {
fileName = _name
}
if mimeType == nil, let _extension = url.pathExtension {
switch _extension.lowercaseString {
case "jpeg", "jpg":
self.mimeType = "image/jpeg"
case "png":
self.mimeType = "image/png"
default:
self.mimeType = "application/octet-stream"
}
}
}
init( name: String, withData data: NSData, withMimeType mimeType: String ) {
self.name = name
self.data = data
self.fileName = name
self.mimeType = mimeType
}
}
class FileUploader {
private var parameters = [String:String]()
private var files = [FileUploadInfo]()
private var headers = [String:String]()
func setValue( value: String, forParameter parameter: String ) {
parameters[parameter] = value
}
func setValue( value: String, forHeader header: String ) {
headers[header] = value
}
func addParametersFrom( map map: [String:String] ) {
for (key,value) in map {
parameters[key] = value
}
}
func addHeadersFrom( map map: [String:String] ) {
for (key,value) in map {
headers[key] = value
}
}
func addFileURL( url: NSURL, withName name: String, withMimeType mimeType:String? = nil ) {
files.append( FileUploadInfo( name: name, withFileURL: url, withMimeType: mimeType ) )
}
func addFileData( data: NSData, withName name: String, withMimeType mimeType:String = "application/octet-stream" ) {
files.append( FileUploadInfo( name: name, withData: data, withMimeType: mimeType ) )
}
func uploadFile( request sourceRequest: NSURLRequest ) -> Request? {
var request = sourceRequest.mutableCopy() as! NSMutableURLRequest
let boundary = "FileUploader-boundary-\(arc4random())-\(arc4random())"
request.setValue( "multipart/form-data;boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let data = NSMutableData()
for (name, value) in headers {
request.setValue(value, forHTTPHeaderField: name)
}
// Amazon S3 (probably others) wont take parameters after files, so we put them first
for (key, value) in parameters {
data.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
data.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
}
for fileUploadInfo in files {
data.appendData( "\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)! )
data.appendData( "Content-Disposition: form-data; name=\"\(fileUploadInfo.name)\"; filename=\"\(fileUploadInfo.fileName)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
data.appendData( "Content-Type: \(fileUploadInfo.mimeType)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
if fileUploadInfo.data != nil {
data.appendData( fileUploadInfo.data! )
}
else if fileUploadInfo.url != nil, let fileData = NSData(contentsOfURL: fileUploadInfo.url!) {
data.appendData( fileData )
}
else { // ToDo: report error
return nil
}
}
data.appendData("\r\n--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
return Alamofire.upload( request, data: data )
}
}
This should work for you too!

Related

App returning [] and [[[]]]] multiple times instead of numbers

I am using firebase to store a users location into the database, and I am getting returned this, I am not sure if it is an error or just something was interpreted wrong:
[]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"]\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"]\\\\\\\\\\\\\\\"]\\\\\\\"]\\\"]\"]"]
This above but like 10x longer
Full Code:
import SwiftUI
import MapKit
import Firebase
import CoreLocationUI
struct MapView: View {
#StateObject private var viewModel = ContentViewModel()
#State var address = ""
#State var addresses:[String] = []
#State var realLat:[String] = []
#State var realLong:[String] = []
var body: some View {
NavigationView {
VStack {
List(0..<realLat.count, id: \.self) {i in Text(realLat[i]) }
List(0..<realLong.count, id: \.self) {i in Text(realLong[i]) }
}
.onAppear(perform: {
downloadLatServerData()
downloadLongServerData()
})
}
}
func downloadLatServerData() {
//address = "Tokyo" // <--- here for testing
//addresses.append(address) // <--- here for testing
let db = Firestore.firestore()
db.collection("UserInfo").addSnapshotListener {(snap, err) in
if err != nil{
print("\(String(describing: err))")
return
}
for i in snap!.documentChanges {
let documentId = i.document.documentID
if let latCoordinate = i.document.get("lat") as? String {
DispatchQueue.main.async {
realLat.append(latCoordinate)
print("\(realLat)")
}
}
}
}
}
func downloadLongServerData() {
//address = "Tokyo" // <--- here for testing
//addresses.append(address) // <--- here for testing
let db = Firestore.firestore()
db.collection("UserInfo").addSnapshotListener {(snap, err) in
if err != nil{
print("\(String(describing: err))")
return
}
for i in snap!.documentChanges {
let documentId = i.document.documentID
if let longCoordniate = i.document.get("long") as? String {
DispatchQueue.main.async {
realLong.append(longCoordniate)
print("\(realLong)")
}
}
}
}
}
}
Sample Numbers:
Lat: -9128653.12
Long: -917532
Did those numbers 4 times, for 4 different users.
try this:
use realLat.append(latCoordinate) not realLat.append("\(realLat)")
and similarly for realLong.
use realLong.append(longCoordniate) not realLong.append("\(realLong)")

Save String Array With #AppStorage

In the following example I am saving a String with #AppStorage:
struct ContentView: View {
#AppStorage("text") private var text = ""
var body: some View {
Button("Append text: \(text)") {
text.append("APPEND")
}
}
}
But I want to save a String array, something like this:
#AppStorage("text") private var text = [
"APPEND",
"APPEND"
]
class Storage: NSObject {
static func archiveStringArray(object : [String]) -> Data {
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: false)
return data
} catch {
fatalError("Can't encode data: \(error)")
}
}
static func loadStringArray(data: Data) -> [String] {
do {
guard let array = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [String] else {
return []
}
return array
} catch {
fatalError("loadWStringArray - Can't encode data: \(error)")
}
}}
VIEW_
struct ContentView: View {
#State var TempTextArray: [String] = []
#AppStorage("textArray", store: UserDefaults(suiteName: "group.de.domain.MyApp")) var items: Data = Data()
var body: some View {
VStack(spacing: 30){
Button("Append text:") {
TempTextArray.append("Append")
items = Storage.archiveStringArray(object: TempTextArray)
}
Button("GET String Array"){
print(Storage.loadStringArray(data: items))
}
}
}}

Pre-enter text in a textfield in SwiftUI

I was able to solve my problem i had earlier on how to update data in Firestore via UI. Now the next problem:
I would like to have my Firebase-Stored Data pre-entered in a text field so you can just !edit! the text in the fields you want instead of writing all data new in every single field. As you can see, the only thing i was able to do, is getting the stored data in the text field as placeholder, which means you have to re-write all data in case you want to update just 1 field.
CODE:
import SwiftUI
import Firebase
struct ContentViewVier: View {
#ObservedObject var dataDrei = getDataZwei()
var body: some View {
NavigationView{
ZStack(alignment: .top){
GeometryReader{_ in
// Home View....
Text("Bitte Seriennummer eingeben").foregroundColor(.black)
}.background(Color("FarbeSeriennummerStartbildschirm").edgesIgnoringSafeArea(.all))
CustomSearchBarEdit(dataZwei: self.$dataDrei.datasZwei).padding(.top)
}.navigationBarTitle("")
.navigationBarHidden(true)
}
}
}
struct CustomSearchBarEdit : View {
#State var txt = ""
#Binding var dataZwei : [dataTypeZwei]
var body : some View{
VStack(spacing: 0){
HStack{
TextField("Nach Seriennummer suchen", text: self.$txt).opacity(100).foregroundColor(.black)
if self.txt != ""{
Button(action: {
self.txt = ""
}) {
Text("Abbrechen")
}
.foregroundColor(.black)
}
}.padding()
if self.txt != ""{
if
self.dataZwei.filter({$0.sn.lowercased() .contains(self.txt.lowercased())}).count == 0 {
Text("Es wurde kein Gerät mit dieser Seriennummer gefunden").foregroundColor(Color.red.opacity(0.6)).padding()
}
else{
List(self.dataZwei.filter{$0.sn.contains(self.txt.lowercased())}){j in
NavigationLink(destination: DetailZwei(data: j)) {
Text(j.sn)
}
Text(j.typ)
}.frame(height: UIScreen.main.bounds.height / 5)
}
}
}.background(Color.white)
.padding()
}
}
class getDataZwei : ObservableObject{
#Published var datasZwei = [dataTypeZwei]()
init() {
let db = Firestore.firestore()
db.collection("Geräte").getDocuments { (snap, err) in
if err != nil{
print((err?.localizedDescription)!)
return
}
for i in snap!.documents{
let id = i.documentID
let sn = i.get("Seriennummer") as! String
let objekt = i.get("Objekt") as! String
let str = i.get("Strasse") as! String
let pos = i.get("Position") as! String
let typ = i.get("Gerätetyp") as! String
let ida = i.get("Installation")as! String
let lg = i.get("LeasingOderGekauft")as! String
let la = i.get("LeasingAblaufdatum")as! String
let ga = i.get("GarantieAblaufdatum")as! String
let nr = i.get("Hausnummer")as! String
let plz = i.get("Postleitzahl")as! String
let ort = i.get("Ort")as! String
let vp = i.get("Verantwortlich")as! String
let tel = i.get("Telefonnummer")as! String
let zusatz = i.get("Zusätzlich")as! String
let ed = i.get("EingetragenDurch")as! String
let ldvds = i.get("LieferungBeiVDS")as! String
self.datasZwei.append(dataTypeZwei(id: id, sn: sn, pos: pos, typ: typ, ida: ida, lg: lg, la: la, ga: ga, objekt: objekt, str: str, nr: nr, plz: plz, ort: ort, vp: vp, tel: tel, zusatz: zusatz, ed: ed, ldvds: ldvds))
}
}
}
}
struct dataTypeZwei : Identifiable, Codable {
var id: String? = UUID().uuidString
var sn : String
var pos : String
var typ : String
var ida : String
var lg : String
var la : String
var ga : String
var objekt : String
var str : String
var nr : String
var plz : String
var ort : String
var vp : String
var tel : String
var zusatz : String
var ed : String
var ldvds : String
enum CodingKeys: String, CodingKey {
case sn = "Seriennummer"
case objekt = "Objekt"
case str = "Strasse"
case nr = "Hausnummer"
case ort = "Ort"
case vp = "Verantwortlich"
case tel = "Telefonnummer"
case pos = "Position"
case typ = "Gerätetyp"
case ida = "Installation"
case lg = "LeasingOderGekauft"
case la = "LeasingAblaufdatum"
case ga = "GarantieAblaufdatum"
case zusatz = "Zusätzlich"
case plz = "Postleitzahl"
case ed = "EingetragenDurch"
case ldvds = "LieferungBeiVDS"
}
}
struct DetailZwei : View {
var data : dataTypeZwei
#State var viewModel = GerätEditieren()
#State var serie: String? = nil
#Environment(\.presentationMode) var presentationMode
var body : some View {
NavigationView {
ScrollView {
Group {
Section(header: Text("Gerät")) {
Text("Seriennummer")
TextField(data.sn, text: $viewModel.gerät.sn).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Objekt")
TextField(data.objekt, text: $viewModel.gerät.objekt).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Gerätetyp")
TextField(data.typ, text: $viewModel.gerät.typ).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Geräteposition")
TextField(data.pos, text: $viewModel.gerät.pos).textFieldStyle(RoundedBorderTextFieldStyle())
}
Group {
Text("Installationsdatum")
TextField(data.ida, text: $viewModel.gerät.ida).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Leasing oder Gekauft?")
TextField(data.lg, text: $viewModel.gerät.lg).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Ablaufdatum Leasing")
TextField(data.la, text: $viewModel.gerät.la).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Ablaufdatum Garantie")
TextField(data.ga, text: $viewModel.gerät.ga).textFieldStyle(RoundedBorderTextFieldStyle())
}
Section(header: Text("Adresse")) {
Text("Strasse")
TextField(data.str, text: $viewModel.gerät.str).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Hausnummer")
TextField(data.nr, text: $viewModel.gerät.nr).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Postleitzahl")
TextField(data.plz, text: $viewModel.gerät.plz).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Ort")
TextField(data.ort, text: $viewModel.gerät.ort).textFieldStyle(RoundedBorderTextFieldStyle())
}
Section(header: Text("Kontakt")) {
Text("Ansprechperson")
TextField(data.vp, text: $viewModel.gerät.vp).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Telefonnummer")
TextField(data.tel, text: $viewModel.gerät.tel).textFieldStyle(RoundedBorderTextFieldStyle())
}
Section(header: Text("VDS")) {
Text("Eingetragen durch")
TextField(data.ed, text: $viewModel.gerät.ed).textFieldStyle(RoundedBorderTextFieldStyle())
Text("Lieferdatum VDS")
TextField(data.ldvds, text: $viewModel.gerät.ldvds).textFieldStyle(RoundedBorderTextFieldStyle())
}
Section(header: Text("Zusätzliche Informationen")) {
Text("Zusätzliche Informationen")
TextField(data.zusatz, text: $viewModel.gerät.zusatz).textFieldStyle(RoundedBorderTextFieldStyle())
}
}.padding()
.navigationBarTitle("Gerät bearbeiten", displayMode: .inline)
.navigationBarItems(leading: Button(action: { self.handleCancelTapped() }, label: {
Text("Abbrechen")
}),
trailing: Button(action: { self.handleDoneTapped() }, label: {
Text("Speichern")
})
// .disabled(!viewModel.modified)
)
}
}
}
func handleCancelTapped() {
dismiss()
}
func handleDoneTapped() {
let db = Firestore.firestore()
let docRef = db.collection("Geräte").document(data.id!)
print("setting data")
docRef.updateData(["Seriennummer": "\(viewModel.gerät.sn)", "Objekt": "\(viewModel.gerät.objekt)", "Strasse": "\(viewModel.gerät.str)", "Hausnummer": "\(viewModel.gerät.nr)", "Ort": "\(viewModel.gerät.ort)", "Verantwortlich": "\(viewModel.gerät.vp)", "Telefonnummer": "\(viewModel.gerät.tel)", "Position": "\(viewModel.gerät.pos)", "Gerätetyp": "\(viewModel.gerät.typ)", "Installation": "\(viewModel.gerät.ida)", "LeasingOderGekauft": "\(viewModel.gerät.lg)", "LeasingAblaufdatum": "\(viewModel.gerät.la)", "GarantieAblaufdatum": "\(viewModel.gerät.ga)", "Zusätzlich": "\(viewModel.gerät.zusatz)", "Postleitzahl": "\(viewModel.gerät.plz)", "EingetragenDurch": "\(viewModel.gerät.ed)", "LieferungBeiVDS": "\(viewModel.gerät.ldvds)"]){ (error) in
if let error = error {
print("error = \(error)")
} else if self.viewModel.gerät.sn == "" {
self.viewModel.gerät.sn = self.data.sn
}
else {
print("data uploaded successfully")
}
}
dismiss()
}
func dismiss() {
presentationMode.wrappedValue.dismiss()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentViewVier()
}
}
This belong to your viewModel to initialize the Published values with the exact value.
Another option is to set the State variables, which you pass to your TextField with the actual value.
#State var vp : String
init(data: Data) { 
self._vp = State(initialValue: data.vp) //<< here set the value from Firebase
}
TextField(data.vp, text: $vp).textFieldStyle(RoundedBorderTextFieldStyle())

Swift 2 How do I isolate resources in a series of NSMutableURLRequests?

Assume I've already logged to two accounts and have obtained unique session cookies for each.
When executing ViewController.run(), which uses nested closures, a series of 80 unique URL requests is made (40 for each of the two accounts) .
Though I'm able to make all 80 unique URL requests, somehow one account will sometimes make a request of a URL that only the other account should be making.
I'm pretty certain the resources between each account as well as each account's request are isolated. Both executions of run() construct their own instances of Visit(_:), URLVisitor(_:) and Request(_:).
Note: assume that neither account's username array contains a username that the other has in it's array.
ViewController.swift
func run(completion: () -> Void) {
// 40 usernames appended to array
var usernames: [String] = ["username1",..., username40]
for username in usernames {
let visit = Visit()
visit.sessionCookie = sessionCookie
visit.visitProfile(username) {
NSThread.sleepForTimeInterval(5.0)
}
}
}
Visit.swift
var contentsOfURL = NSString()
var sessionCookie = String()
func visitprofile(username: String, completion: () -> Void) {
let url = "https://www.someurl.com/profile/\(username)"
let encodedURL = url.stringByAddingPercentEncodingWithAllowedCharacters(
NSCharacterSet.URLFragmentAllowedCharacterSet()),
URL = NSURL(string: encodedURL!)
let vis = URLVisitor(URL: URL!)
vis.sessionCookie = self.sessionCookie
vis.execute {
if vis.containsString(profileName) {
print("\(profileName) visited: OK")
} else {
print("\(profileName) visited: FAIL")
}
completion()
}
}
URLVisitor.swift
var contentsOfURL = NSString()
var sessionCookie = String()
var URL = NSURL()
init(URL: NSURL) {
self.URL = URL
}
func execute(completion: () -> Void) {
let request = Request()
request.sessionCookie = self.sessionCookie
request.accessToken = self.accessToken
request.sessionCookie = self.sessionCookie
request.sendRequest(self.URL, completion: () -> Void) {
self.sessionCookie = request.sessionCookie
self.contentsOfURL = request.contentsOfURL
completion()
}
}
Request.swift: NSObject, NSURLSessionDelegate
var contentsOfURL = NSString()
var responseCookies = String()
var sessionCookie = String()
func sendRequest(URL: NSURL, completion: () -> Void) {
var request = NSMutableURLRequest(URL: URL)
var session = NSURLSession.sharedSession()
var config = NSURLSessionConfiguration.defaultSessionConfiguration()
if sessionCookie != "" {
config.HTTPCookieStorage = nil
config.requestCachePolicy = .ReloadIgnoringLocalAndRemoteCacheData
request.setValue(sessionCookie, forHTTPHeaderField: "Cookie")
session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
}
request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding)
request.HTTPMethod = "GET"
let task = session.dataTaskWithRequest(request) { (data, response, error) in
let response = response as! NSHTTPURLResponse
do {
self.contentsOfURL = try NSString(contentsOfURL: URL, encoding: NSUTF8StringEncoding)
} catch{
}
if self.sessionCookie == "" {
self.sessionCookie = // obtained here during login
}
completion()
}
task.resume()
}

How to upload image with parameters using Alamofire in Swift

I am developing an iPhone application with swift. and I'am using Alamofire framework for handling http requests. I use Alamofire.request for POST , GET and etc like this:
Alamofire.request(.POST, myURL , parameters: ["a": "1", "b" : "2" ])
.response { (request, response, data, error) in
}
And I use Alamofire.upload to upload image to server this :
Alamofire.upload(.POST, uploadURL , fileURL)
And both works perfectly, but now I want to upload an image and also send some parameters with, and my content type should be multipart/form-data and Alamofire.upload does not accept parameters.
There are two more question on SO about this issue with swift, which first one is not using Alamofire (and really, why not?) and in second one, mattt (Alamofire Developer) cited to use encoding parameters.
I checked his example, but still couldn't figure out how to do that.
Can any one please help me solve this problem?
Thank you! :)
you can use Alamofire 3.0+ below code
func uploadImageAndData(){
//parameters
let gender = "M"
let firstName = "firstName"
let lastName = "lastName"
let dob = "11-Jan-2000"
let aboutme = "aboutme"
let token = "token"
var parameters = [String:AnyObject]()
parameters = ["gender":gender,
"firstName":firstName,
"dob":dob,
"aboutme":about,
"token":token,
"lastName":lastName]
let URL = "http://yourserviceurl/"
let image = UIImage(named: "image.png")
Alamofire.upload(.POST, URL, multipartFormData: {
multipartFormData in
if let imageData = UIImageJPEGRepresentation(image, 0.6) {
multipartFormData.appendBodyPart(data: imageData, name: "image", fileName: "file.png", mimeType: "image/png")
}
for (key, value) in parameters {
multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
}
}, encodingCompletion: {
encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
print("s")
upload.responseJSON {
response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
case .Failure(let encodingError):
print(encodingError)
}
})
}
SWIFT 2 AlamoFire Simple Image Upload (REST API)
#amit gupta It seems answer contains big overhead. AlamoFire contain load of simplified solution. Alamofire.request method contains several simplified overload which can use to upload in simple manner. By using Alamofire.request( method developer can get rid of encoding overhead.
HTTP Status 415 gives because of not specifying the correct media type.
Please check my solution below.
import UIKit
import Alamofire
class ViewController: UIViewController {
#IBOutlet var imageView: UIImageView!
#IBOutlet var btnUpload: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
func successDataHandler(responseData:String){
print ("IMAGE UPLOAD SUCCESSFUL !!!")
}
func failureDataHandler(errorData:String){
print (" !!! IMAGE UPLOAD FAILURE !!! ")
}
#IBAction func actionUpload(sender: AnyObject) {
let URL = "http://m8coreapibeta.azurewebsites.net/api/cards/SaveImages"
let postDataProlife:[String:AnyObject] = ["CardId":(dataCardDetail?.userId)!,"ImageType":1,"ImageData":imageView.image!]
uplaodImageData(URL, postData: postDataProlife, successHandler: successDataHandler, failureHandler: failureDataHandler)
}
func uplaodImageData(RequestURL: String,postData:[String:AnyObject]?,successHandler: (String) -> (),failureHandler: (String) -> ()) -> () {
let headerData:[String : String] = ["Content-Type":"application/json"]
Alamofire.request(.POST,RequestURL, parameters: postData, encoding: .URLEncodedInURL, headers: headerData).responseString{ response in
switch response.result {
case .Success:
print(response.response?.statusCode)
successHandler(response.result.value!)
case .Failure(let error):
failureHandler("\(error)")
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Almaofire with swift 3.0
Alamofire.upload(multipartFormData: { multipartFormData in
var index = 1
for image in imageArray {
let imageData: Data = (UIImageJPEGRepresentation(image, 1.0) as Data?)!
multipartFormData.append(imageData, withName: "home-\(index)", fileName: "home-\(index)", mimeType: "image/jpeg")
index += 1
}
}, with: requestName, encodingCompletion: { result in
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
print("Image(s) Uploaded successfully:\(response)")
}
case .failure(let encodingError):
print("encodingError:\(encodingError)")
}
})
Swift 4 with Alamofire 4
let isConnected = connectivity.isConnectedToInternet()
func updateProfile(firstName:String,lastName:String ,imageData:Data?,completion: #escaping (isValidUser)->()) {
if self.isConnected {
var parameters : [String:String] = [:]
parameters["auth_key"] = loginUser?.authKey!
parameters["first_name"] = firstName
parameters["last_name"] = lastName
let url = "\(baseUrl)\(basicAuthenticationUrl.updateProfile)"
print(url)
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
if let data = imageData {
multipartFormData.append(data, withName: "image_url", fileName: "image.png", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url, method: .post) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
print("Succesfully uploaded = \(response)")
if let err = response.error{
print(err)
return
}
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
}
}
}
}
Almaofire with swift 2.0 just copy and paste below code.here m asumming JSON response from server
func uploadImageRemote (imageData : NSData?) -> Dictionary <String,AnyObject>{
var imageDictionary = Dictionary<String,AnyObject>()
var tokenHeaders:[String:String]! = ["x-access-token":Constants.kUserDefaults.stringForKey("userToken")!]
Alamofire.upload(
.POST,
"http://52.26.230.146:3300/api/profiles/imageUpload",headers:tokenHeaders,
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(data: imageData!, name: "upload", fileName: "imageFileName.jpg", mimeType: "image/jpeg")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
print("Uploading Avatar \(totalBytesWritten) / \(totalBytesExpectedToWrite)")
dispatch_async(dispatch_get_main_queue(),{
})
}
upload.responseJSON { response in
guard response.result.error == nil else {
print("error calling GET \(response.result.error!)")
return
}
if let value = response.result.value {
print("Success JSON is:\(value)")
if let result = value as? Dictionary<String, AnyObject> {
imageDictionary["imageUrl"] = result["url"]
}
}
dispatch_async(dispatch_get_main_queue(),{
//Show Alert in UI
print("Avatar uploaded");
})
}
case .Failure(let encodingError):
//Show Alert in UI
print("Avatar not uploaded \(encodingError)");
}
}
);
return imageDictionary
}
To use encoding Parameters, make a ParameterEncoding variable, assign it a encoding type (case of the enum which include .JSON, .URL) and then use the encode function with your NSURLRequest and the parameters. This function returns a tuple of two element, the first being the resulting NSURLRequest and the second being the resulting possible NSError.
Here's how I used it for a custom header I needed in a project
var parameterEncoding:ParameterEncoding!
switch method {
case .POST, .PUT :
parameterEncoding = ParameterEncoding.JSON
default :
parameterEncoding = ParameterEncoding.URL
}
var alamoRequest = Alamofire.Manager.sharedInstance.request(parameterEncoding.encode(mutableURLRequest, parameters: parameters).0)

Resources