使用网络视图下载文件
Downloading a file using web view
在一个项目中,我想在 Web 视图中加载的 http 页面中下载 mp3 文件。下载的文件可以通过 phone 驱动器或保管箱等应用程序打开。
当用户在 Web 视图中单击 link 时,它应该将其下载到 iphone。
在服务器端,mp3 文件位于 webroot 之外。所以,下载的 link 类似于 "download.php?id=554"
有人可以帮我解决这个问题吗?
我想知道有没有办法实现这一目标。谢谢
编辑
我添加了这个代表
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
}
但是还是不知道怎么下载?
我没有得到你的实际要求,但你可以使用下面的代码从 URL 下载文件。
NSString *stringURL = @"http://www.somewhere.com/Untitled.mp3";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
当您在网页上按 links 时,您可以从 UIWebView 委托方法
获取 mp3 文件 url(从 NSURLRequest 对象读取)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return NO;
}
在 Swift、
中创建 UIWebView
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)
}
当用户点击网页中的link时,UIWebView会自动调用"shouldStartLoadWithRequest"方法,使用下面的代码下载文件
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
}
希望对您有所帮助
为了能够检测来自 link 的下载,您需要首先检查 shouldStartLoadWithRequest
中的请求和导航类型。
您需要检查一些内容,请求 HTTPMethod
将是 POST,导航类型也将是 UIWebViewNavigationTypeFormSubmitted
、UIWebViewNavigationTypeFormResubmitted
或 UIWebViewNavigationTypeLinkClicked
。您还需要解析请求 URL 的查询字符串,它将有一个 response-content-disposition
、attachment
或 dl
键,如果有,则它是文件下载。然后您需要为请求创建一个 NSURLConnection
并启动它,然后在 Web 视图委托中 return NO
。
以下是我在我的应用程序中检查下载的方式。 (进入 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;
}
然后您需要添加 NSURLConnection
委托方法 didReceiveResponse
。我检查 header 字段中的一些键,然后如果它们通过,您可以开始下载,或者如果结果不是下载,则让 Web 视图继续加载。 (进入 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];
}
SwiftHTTP (https://github.com/daltoniam/swiftHTTP) 让我成为可能!
就是这么简单我的朋友,
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];
}
建议在单独的线程中执行代码。
对于大量下载:
-(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 !");
});
}
});
}
在一个项目中,我想在 Web 视图中加载的 http 页面中下载 mp3 文件。下载的文件可以通过 phone 驱动器或保管箱等应用程序打开。
当用户在 Web 视图中单击 link 时,它应该将其下载到 iphone。
在服务器端,mp3 文件位于 webroot 之外。所以,下载的 link 类似于 "download.php?id=554"
有人可以帮我解决这个问题吗? 我想知道有没有办法实现这一目标。谢谢
编辑
我添加了这个代表
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
}
但是还是不知道怎么下载?
我没有得到你的实际要求,但你可以使用下面的代码从 URL 下载文件。
NSString *stringURL = @"http://www.somewhere.com/Untitled.mp3";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
当您在网页上按 links 时,您可以从 UIWebView 委托方法
获取 mp3 文件 url(从 NSURLRequest 对象读取)- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return NO;
}
在 Swift、
中创建 UIWebViewoverride 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)
}
当用户点击网页中的link时,UIWebView会自动调用"shouldStartLoadWithRequest"方法,使用下面的代码下载文件
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
}
希望对您有所帮助
为了能够检测来自 link 的下载,您需要首先检查 shouldStartLoadWithRequest
中的请求和导航类型。
您需要检查一些内容,请求 HTTPMethod
将是 POST,导航类型也将是 UIWebViewNavigationTypeFormSubmitted
、UIWebViewNavigationTypeFormResubmitted
或 UIWebViewNavigationTypeLinkClicked
。您还需要解析请求 URL 的查询字符串,它将有一个 response-content-disposition
、attachment
或 dl
键,如果有,则它是文件下载。然后您需要为请求创建一个 NSURLConnection
并启动它,然后在 Web 视图委托中 return NO
。
以下是我在我的应用程序中检查下载的方式。 (进入 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;
}
然后您需要添加 NSURLConnection
委托方法 didReceiveResponse
。我检查 header 字段中的一些键,然后如果它们通过,您可以开始下载,或者如果结果不是下载,则让 Web 视图继续加载。 (进入 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];
}
SwiftHTTP (https://github.com/daltoniam/swiftHTTP) 让我成为可能!
就是这么简单我的朋友,
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];
}
建议在单独的线程中执行代码。
对于大量下载:
-(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 !");
});
}
});
}