我正在尝试将pdf文件从服务器下载到设备。这是我正在使用的代码
- (id)initwithURL:(NSString*)remoteFileLocation andFileName:(NSString*)fileName{
//Get path to the documents folder
NSString *resourcePathDoc = [[NSString alloc] initWithString:[[[[NSBundle mainBundle]resourcePath]stringByDeletingLastPathComponent]stringByAppendingString:@"/Documents/"]];
localFilePath = [resourcePathDoc stringByAppendingString:fileName];
BOOL fileExists = [[NSFileManager defaultManager]fileExistsAtPath:localFilePath];
if (fileExists == NO) {
NSURL *url = [NSURL URLWithString:remoteFileLocation];
NSData *data = [[NSData alloc] initWithContentsOfURL: url];
//Write the data to the local file
[data writeToFile:localFilePath atomically:YES];
}
return self;
}
其中remoteFileLocation是NSString,其值为http://topoly.com/optimus/irsocial/Abs/Documents/2009-annual-report.pdf 在运行应用程序崩溃时,仅在NSData上发出SIGABRT错误。它提供的唯一有用信息是
由于未捕获的异常'NSInvalidArgumentException'而终止应用,原因:' - [NSURL长度]:无法识别的选择器发送到实例0xc87b600'
如何解决这个问题?
答案 0 :(得分:3)
由于您的PDF文件太大,所以如果您进行同步下载,下载时间太长,所以我坚持要创建一个异步下载器并使用它。我已经为此添加了代码。
步骤1:创建文件'FileDownloader.h'
#define FUNCTION_NAME NSLog(@"%s",__FUNCTION__)
#import <Foundation/Foundation.h>
@protocol fileDownloaderDelegate <NSObject>
@optional
- (void)downloadProgres:(NSNumber*)percent forObject:(id)object;
@required
- (void)downloadingStarted;
- (void)downloadingFinishedFor:(NSURL *)url andData:(NSData *)data;
- (void)downloadingFailed:(NSURL *)url;
@end
@interface FileDownloader : NSObject
{
@private
NSMutableURLRequest *_request;
NSMutableData *downloadedData;
NSURL *fileUrl;
id <fileDownloaderDelegate> delegate;
double totalFileSize;
}
@property (nonatomic, strong) NSMutableURLRequest *_request;
@property (nonatomic, strong) NSMutableData *downloadedData;
@property (nonatomic, strong) NSURL *fileUrl;
@property (nonatomic, strong) id <fileDownloaderDelegate> delegate;
- (void)downloadFromURL:(NSString *)urlString;
@end
步骤2:使用FileDownloader.m
创建.m文件#import "FileDownloader.h"
@implementation FileDownloader
@synthesize _request, downloadedData, fileUrl;
@synthesize delegate;
- (void)downloadFromURL:(NSString *)urlString
{
[self setFileUrl:[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
self._request = [NSMutableURLRequest requestWithURL:self.fileUrl cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0f];
NSURLConnection *cn = [NSURLConnection connectionWithRequest:self._request delegate:self];
[cn start];
}
#pragma mark - NSURLConnection Delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if([delegate respondsToSelector:@selector(downloadingStarted)])
{
[delegate performSelector:@selector(downloadingStarted)];
}
totalFileSize = [response expectedContentLength];
downloadedData = [NSMutableData dataWithCapacity:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[downloadedData appendData:data];
if([delegate respondsToSelector:@selector(downloadProgres:forObject:)])
{
[delegate performSelector:@selector(downloadProgres:forObject:) withObject:[NSNumber numberWithFloat:([downloadedData length]/totalFileSize)] withObject:self];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
if([delegate respondsToSelector:@selector(downloadingFailed:)])
{
[delegate performSelector:@selector(downloadingFailed:) withObject:self.fileUrl];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if([delegate respondsToSelector:@selector(downloadingFinishedFor:andData:)])
{
[delegate performSelector:@selector(downloadingFinishedFor:andData:) withObject:self.fileUrl withObject:self.downloadedData];
}
}
@end
第3步:在viewController中导入文件#import "FileDownloader.h"
和fileDownloaderDelegate
步骤4:在viewCOntroller的.m文件中定义以下Delegate方法
- (void)downloadingStarted;
- (void)downloadingFinishedFor:(NSURL *)url andData:(NSData *)data;
- (void)downloadingFailed:(NSURL *)url;
步骤5:创建FileDownloader的对象并将URL设置为Download that it it。
FileDownloader *objDownloader = [[FileDownloader alloc] init];
[objDownloader setDelegate:self];
[objDownloader downloadFromURL:@"Your PDF Path URL here];
第6步:将文件保存到所需位置
- (void)downloadingFinishedFor:(NSURL *)url andData:(NSData *)data;
方法。
答案 1 :(得分:1)
您的remoteFileLocation
参数值似乎是NSURL
对象,而不是NSString
。仔细检查您获取/创建remoteFileLocation
的方式,并确认它确实是NSString
。
此代码还存在其他几个问题。创建Documents目录路径的正确方法如下:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths[0];
NSString *localFilePath = [resourcePathDoc stringByAppendingPathComponent:fileName];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:localFilePath];
if (!fileExists) {
NSURL *url = [NSURL URLWithString:remoteFileLocation];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
//Write the data to the local file
[data writeToFile:localFilePath atomically:YES];
}
答案 2 :(得分:0)
GCD可用于海量文件。您可以在第二个线程上下载同步文件,如果愿意,可以回发到主线程。您还可以使用操作队列。
您确实也可以使用NSURLConnection中的委托方法,允许您处理主线程上的回调。然而,定义自己的委托已经过时,因为您可以从NSURLConnection本身实现委托。