I am using AFNetworking to send a HTTP request to a Django server to download a file to iPhone. However, neither do the console print out "Success" or "Error". I also cannot find the file in the specific dir ".../database". For the server side, the log file is correct ([22/Jan/2015 16:45:49] "GET /main/receivefile/ HTTP/1.1" 200 16811) and I can see the request and there is no error. This is my client side code:
var parameters = ["username":"u987103"];
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let outPath = String(format: "%#/database/tmp.txt", documentsPath)
self.man = AFHTTPRequestOperationManager()
self.op = self.man.GET(url, parameters: parameters,
success: {(operation:AFHTTPRequestOperation!,responseObject:AnyObject!) in
println("Success")
}
, failure:{(operation:AFHTTPRequestOperation!,error:NSError!) in
println("Error: %#",error);
})
op.outputStream = NSOutputStream(toFileAtPath: outPath, append: false)
The code corresponding to the request URL in the Django server is:
def retrieve_file(request):
filename = os.path.basename(m_path)
path = os.path.join(settings.MEDIA_ROOT,m_path)
wrapper = FileWrapper(file(path))
response = HttpResponse(wrapper,content_type="text/plain")
response['Content-Disposition'] = 'attachment; filename="'+filename+'"'
return response
I have tested to download the file using Chrome and as soon as I enter the URL and hit "enter", the file is downloaded to my download folder. So could anyone tell me why it does not work for AFNetwokring?
Yes that is correct.
Take a look at the doc here - http://cocoadocs.org/docsets/AFNetworking/2.0.0/Classes/AFHTTPRequestOperationManager.html#//api/name/responseSerializer. You need to specify a response serializer for AFHttpRequestOperationManager.
It seems like you are downloading a plain text file, so you can use the default serializer. Add this call:
self.man.responseSerializer = AFHttpResponseSerializer()
before you call self.man.GET.
The https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-2.0-Migration-Guide has some details on how the response and request serializers work.
The code below is the correct way to do it for AFNetwokring 2.5.0
Reference: http://cocoadocs.org/docsets/AFNetworking/2.5.0/
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var man = AFURLSessionManager(sessionConfiguration: configuration)
var URL = NSURL(string: "http://www.google.com/images/srpr/logo11w.png")
var request = NSURLRequest(URL:URL!)
var downloadTask = man.downloadTaskWithRequest(request, progress: nil,
destination:{(targetPath:NSURL!,response:NSURLResponse!) -> NSURL! in
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let outPath = String(format: "%#/download/", documentsPath)
var url:NSURL! = NSURL(fileURLWithPath: outPath)
return url.URLByAppendingPathComponent(response.suggestedFilename as String!)
},
completionHandler:{(response:NSURLResponse!,filePath:NSURL!,error:NSError!) in
println(response.suggestedFilename)
})
downloadTask.resume();
Related
I'm trying to download a file (namely 'xp-en.zip') from a certain server. I've already checked that this file exists using contentsOfDirectory(::), but for some reason, after the download is completed the file doesn't show up in the directory it was supposed to have been copied to. I'm using XCode and I thought it could have something to do with the app's permissions (since the destination directory is .documentDirectory), but I tried changing it to the main bundle to no avail.
I also tried downloading from another server ('speedtest.tele2.net') but it didn't work either.
let credential = URLCredential(user: "anonymous", password: "123456", persistence: .permanent)
let fileManager = FileManager.default
func FTPDownloadUpload(download: Bool = true, server: String, path: String){
let localFilePath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
guard let url = URL(string: server) else{
print("Invalid URL")
return
}
let FTPProvider = FTPFileProvider(baseURL: URL(string: "ftp://" + server)!, mode: .passive, credential: credential, cache: URLCache())
if download{
FTPProvider?.copyItem(path: "/" + path, toLocalURL: localFilePath, completionHandler: {x in print("Download completed")})
//I know this completionHandler closure kinda sucks but I don't know what else to put inside it. Keep in mind my program doesn't have anything to do after calling this function
}else{
//This is the upload section. Didn't include it to keep the code shorter
}
}
My function call is:
FTPDownloadUpload(server: "176.74.128.88", path: "xp-en.zip")
I use the code to load URL path hash fragment (such as: index.html#/some-hash-path; but WKWebview not load url.
let path = "www/index.html"
let page = "#/some-hash-path"
let url = Bundle.main.bundleURL.appendingPathComponent(path + page)
self.webView.loadFileURL(url, allowingReadAccessTo: Bundle.main.bundleURL)
It seem that it convert # -> %23 which make invalid path
I got stuck too trying to build the url in an apparently correct way for local files.
The url must be created with URL(string:) initializer, prefixing it manually with file://, and loaded with loadFileURL().
let url = URL(string: "file://\(indexPath)#\(section)")
webView.loadFileURL(url, allowingReadAccessTo: Bundle.main.bundleURL)
Construct URL from string work as expected:
let path = "www/index.html"
let page = "#/some-hash-path"
guard let parsedUrl = URL(string: Bundle.main.bundleURL.absoluteString + path + page) else {
return
}
self.webView.loadFileURL(parsedUrl, allowingReadAccessTo: Bundle.main.bundleURL)
I am trying to open an Excel document that is located on a server. I wrote the following code but it always returns false for UIApplication.shared.canOpenURL(url as URL)
I think I am missing some requirement for deep linking to Excel. Why is iOS not able to understand ms-excel:ofe|u| format?
#objc static func openExcel() {
let originalString = "http://s000.tinyupload.com/download.php?file_id=23290165129849240725&t=2329016512984924072514118"
let encodedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
let encodedURLString = "ms-excel:ofe|u|" + encodedString! + "|n|TestDoc.xlsx|a|App"
if let url = NSURL(string: encodedURLString),
UIApplication.shared.canOpenURL(url as URL) {
UIApplication.shared.openURL(url as URL)
} else if let itunesUrl = NSURL(string: "https://itunes.apple.com/us/app/microsoft-excel/id586683407?mt=8&uo=4"), UIApplication.shared.canOpenURL(itunesUrl as URL) {
UIApplication.shared.openURL(itunesUrl as URL)
}
}
I have analyzed your code and found some mistakes. First, your URL was redirecting to somewhere, as per Microsoft documentation it can't handle redirecting URL's
The URL has to be encoded and must be a direct link to the file (not a
redirect). If the URL is in a format that Office cannot handle, or the
download simply fails, Office will not return the user to the invoking
application.
Here is Microsoft Documentation Link
The second mistake was you are only encoding the URL string containing site URL, you should consider the part after the scheme ms-excel: as a URL and should be encoded.
Because of improper encoding the let url = URL(string: encodedURLString) results nil that's why it is not working as expected.
Here is an example working code:
#objc static func openExcel() {
//replace the below url with yours. may be this one dosen't work
let originalString = "ofe|u|https://pgcconline.blackboard.com/webapps/dur-browserCheck-bb_bb60/samples/sample.xlsx"
let encodedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let encodedURLString = "ms-excel:" + encodedString!
if let url = URL(string: encodedURLString),
UIApplication.shared.canOpenURL(url) {
UIApplication.shared.openURL(url)
} else if let itunesUrl = NSURL(string: "https://itunes.apple.com/us/app/microsoft-excel/id586683407?mt=8&uo=4"), UIApplication.shared.canOpenURL(itunesUrl as URL) {
UIApplication.shared.openURL(itunesUrl as URL)
}
}
Note: From iOS 9 you must whitelist any URL schemes your App wants to query in Info.plist under the LSApplicationQueriesSchemes key (an array of strings):
For example in our case:
When i try to open the URL in the question above I get redirected to this URL, so my guess would be that your code is fine, it just might be that your excel file you're trying to open is really an HTML page since tinyupload apparently blocks direct links to the files.
Maybe try opening a direct excel file download link, https://pgcconline.blackboard.com/webapps/dur-browserCheck-bb_bb60/samples/sample.xlsx (it was the first google result for 'xlsx file sample download')
I have a video that is captured with AVCapture, and I'm trying to upload with AFNetworking with Swift.
Code:
let manager = AFHTTPRequestOperationManager()
let url = "http://localhost/test/upload.php"
var fileURL = NSURL.fileURLWithPath(string: ViewControllerVideoPath)
var params = [
"familyId":locationd,
"contentBody" : "Some body content for the test application",
"name" : "the name/title",
"typeOfContent":"photo"
]
manager.POST( url, parameters: params,
constructingBodyWithBlock: { (data: AFMultipartFormData!) in
println("")
var res = data.appendPartWithFileURL(fileURL, name: "fileToUpload", error: nil)
println("was file added properly to the body? \(res)")
},
success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in
println("Yes thies was a success")
},
failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in
println("We got an error here.. \(error.localizedDescription)")
})
The code above fails, I keep getting
was file added properly to the body? false"
note that ViewControllerVideoPath is a string containing the location of the video which is:
"/private/var/mobile/Containers/Data/Application/1110EE7A-7572-4092-8045-6EEE1B62949/tmp/movie.mov"
using println().... The code above works when I'm uploading a file included in the directory and using:
var fileURL = NSURL.fileURLWithPath(NSBundle.mainBundle().pathForResource("test_1", ofType: "mov")!)
So definitely my PHP code is fine, and the problem lies with uploading that file saved on the device, what am I doing wrong here?
Comments don't allow a full explanation so here is more info;
NSBundle.mainBundle() refers to a path in the bundle file The path in the simulator differs from that of the application ... this is not what you want. There are a number of "folders" you can access based on your needs (private or sharable/files that can get backed up to the cloud). NSPathUtils.h gives a breakdown of the paths available. In keeping with conventions used by most, you should probably create a private path under your application path by doing something like;
- (NSURL *) applicationPrivateDocumentsDirectory{
NSURL *pathURL = [[self applicationLibraryDirecory]URLByAppendingPathComponent:#"MyApplicationName"];
return pathURL;
}
- (NSURL *) applicationLibraryDirecory{
return [[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
}
You can test if it exists, if not, create it ... then store your video files in this path, and pass this to your AVCapture as the location to store the file.
Here are the code that can do following functionality in swift.
1 : Check weather directory exist or not. if not exist then create directory(Directory has given application name) in document directory folder.
2 : Now we have application directory. so all file that from application will write/read in/from this directory.
let file = "file.txt"
let directoryName = “XYZ” // Here “XYZ” is project name.
var error : NSError?
let filemgr = NSFileManager.defaultManager()
let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,
.UserDomainMask, true)
let documentsDirectory = dirPaths[0] as! String
var dataPath = documentsDirectory.stringByAppendingPathComponent(directoryName)
if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) {
NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil, error: &error)
} else {
println("not creted or exist")
}
Now we have Directory so only need to write/read data from directory.
how to write file in document directory in swift
let filePath = dataPath.stringByAppendingPathComponent(file);
let text = "some text"
//writing
text.writeToFile(filePath, atomically: false, encoding: NSUTF8StringEncoding, error: nil);
How to read file from document directory.
let filePath = dataPath.stringByAppendingPathComponent(file);
// Read file
let text2 = String(contentsOfFile: filePath, encoding: NSUTF8StringEncoding, error: nil)
Output :
Hope this will help you.
I am using Azure Mobile Services API endpoint to return a private shared access signature URL to my azure storage container like so:
var blobService = azure.createBlobService(accountName, key, host);
blobService.createContainerIfNotExists(containerName, function(err) {
if (err) {
cb(err, null);
return;
}
// Generate a 5 minute access
var expiryDate = minutesFromNow(5);
var sharedAccessPolicy = {
AccessPolicy: {
Permissions: azure.Constants.BlobConstants.SharedAccessPermissions.WRITE,
Expiry: expiryDate
}
};
// Generate the URL with read access token
var sasURL = blobService.generateSharedAccessSignature(containerName, blobName, sharedAccessPolicy);
var urlForDownloading = sasURL.baseUrl + sasURL.path + '?' + qs.stringify(sasURL.queryString);
cb(null, urlForDownloading);
});
function minutesFromNow(minutes) {
var date = new Date();
date.setMinutes(date.getMinutes() + minutes);
return date;
};
I then return this URL to my iOS client to upload the file and process it as:
client.invokeAPI("document/\(document.idValue).\(document.fileExtension)",
body: nil,
HTTPMethod: "PUT",
parameters: nil,
headers: nil) { result, response, error in
if let dictResult = result as? NSDictionary {
// Get the SAS URL to write directly to the blob storage
if let location = dictResult["location"] as? String {
let url = NSURL(string: location)
let request = NSURLRequest(URL: url)
let uploadTask = session.uploadTaskWithRequest(request, fromFile: localFile) { data, response, error in
if completionBlock != nil {
let success = (error == nil && httpResponse.statusCode == 200)
completionBlock!(success)
}
}
}
}
}
uploadTask.resume()
The iOS client gets a 404 response with a message of
<?xml version="1.0" encoding="utf-8"?><Error><Code>ResourceNotFound</Code><Message>The specified resource does not exist.
The container does exist in the storage account and requests to get blobs from the container with the access keys are successful. This new blob won't exist as it is a new upload, but why am I getting a 404 for a write request to the container?
Found the solution...
let request = NSURLRequest(URL: url) produces a GET request and even passing it to uploadTaskWithRequest persists this request type, whereas I thought this call would change it to a PUT or POST request signifying the upload.
Defining the iOS request as
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "PUT"
was successful. And the response returned was a 201 created.