Reputation: 10192
In a project, i want to download mp3 files in a http page loaded in web view. Downloaded files could be opened by apps like phone drive or dropbox.
When user click to the link in web view it should download it to iphone.
In server side, mp3 files are located outside of webroot. So, the link for download is something like "download.php?id=554"
Anyone can help me on this subject ? I wonder is there a way to achieve this. Thanks
EDIT
I added this delegate
func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
var urlm = request.URL.absoluteURL?.absoluteString
if urlm?.rangeOfString("filename") != nil{
print(urlm)
//code to download (I NEED IT TOO)
return false
}
return true
}
But still don't know how to download ?
Upvotes: 5
Views: 13627
Reputation: 61
It is this simple my friend,
NSString *stringURL = @"http://www.somewhere.com/thefile.png";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"filename.png"];
[urlData writeToFile:filePath atomically:YES];
}
it advisable to execute the code in a separate thread.
For large downloads:
-(IBAction) downloadButtonPressed:(id)sender;{
//download the file in a seperate thread.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Downloading Started");
NSString *urlToDownload = @"http://www.somewhere.com/thefile.png";
NSURL *url = [NSURL URLWithString:urlToDownload];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"filename.png"];
//saving is done on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[urlData writeToFile:filePath atomically:YES];
NSLog(@"File Saved !");
});
}
});
}
Upvotes: 1
Reputation: 10192
SwiftHTTP (https://github.com/daltoniam/swiftHTTP) made it possible to me!
Upvotes: 1
Reputation: 3089
To be able to detect a download from a link like that, you need to first check the request and the navigation type in shouldStartLoadWithRequest
.
You will want to check a few things, the request HTTPMethod
will be POST, also the navigation type will be either UIWebViewNavigationTypeFormSubmitted
, UIWebViewNavigationTypeFormResubmitted
, or UIWebViewNavigationTypeLinkClicked
. You will also need to parse the query string of the requests URL, it will have a response-content-disposition
, attachment
, or dl
key, and if it has one then it is a file download. Then you will need to create a NSURLConnection
for the request and start it, then return NO
in the web view delegate.
Here is how I check for downloads in my app. (Goes in shouldStartLoadWithRequest
)
NSDictionary *dict = [url parseQueryString];
if (([[request.HTTPMethod uppercaseString] isEqualToString:@"POST"] &&
(navigationType == UIWebViewNavigationTypeFormSubmitted ||
navigationType == UIWebViewNavigationTypeFormResubmitted ||
navigationType == UIWebViewNavigationTypeLinkClicked)) || [[dict objectForKey:@"response-content-disposition"] isEqualToString:@"attachment"] || [[dict objectForKey:@"dl"] boolValue] == YES) {
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
return NO;
}
You will then need to add the NSURLConnection
delegate method didReceiveResponse
. I check for some keys in the header fields and then you can start a download if they pass, or have the web view continue loading if it turns out to not be a download. (Goes in didReceiveResponse
)
if (urlResponse.allHeaderFields[@"Content-Disposition"] ||
([[urlResponse.allHeaderFields[@"Content-Type"] lowercaseString] containsString:@"text/html;"] == NO &&
[[urlResponse.allHeaderFields[@"Content-Type"] lowercaseString] containsString:@"charset=utf-8"] == NO )) {
// Start a download with NSURLSession with response.URL and connection.currentRequest
}
else {
[self.webView loadRequest:connection.currentRequest];
[connection cancel];
}
Upvotes: 0
Reputation: 832
I did not get your actual requirement, but you can download the files from a URL using below code.
NSString *stringURL = @"http://www.somewhere.com/Untitled.mp3";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
you can get the mp3 file urls(read from NSURLRequest object) when you press the links on webpage, from UIWebView delegate method
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return NO;
}
Creating a UIWebView in Swift,
override func viewDidLoad() {
super.viewDidLoad()
let webV:UIWebView = UIWebView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height))
webV.loadRequest(NSURLRequest(URL: NSURL(string: "http://www.somewhere.com")))
webV.delegate = self;
self.view.addSubview(webV)
}
When user clicks a link in the web page, the UIWebView will call "shouldStartLoadWithRequest" method automatically, use below code to download the file
func webView(webView: UIWebView!,
shouldStartLoadWithRequest request: NSURLRequest!,
navigationType navigationType: UIWebViewNavigationType) -> Bool {
println("Redirecting URL = \(request.URL)")
//check if this is a mp3 file url and download
if(mp3 file)
{
let request:NSURLRequest = NSURLRequest(request.URL)
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse!, mp3Data: NSData!, error: NSError!) -> Void in
let documentsPath : AnyObject = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0]
let destinationPath:NSString = documentsPath.stringByAppendingString("/Untitled.mp3")
mp3Data.writeToFile(destinationPath, atomically: true)
return false
})
return true
}
I hope this helps
Upvotes: 0