iOS-文件下載某残、大文件下載国撵、斷點(diǎn)下載

20150910174721232.gif

iOS開發(fā)中經(jīng)常會(huì)用到文件的下載與上傳功能,今天咱們來(lái)分享一下文件下載的思路玻墅。文件上傳下篇再說(shuō)介牙。

文件下載分為:小文件下載、大文件下載澳厢。

小文件下載

小文件可以是一張圖片环础,或者一個(gè)文件,這里指在現(xiàn)行的網(wǎng)絡(luò)狀況下基本上不需要等待很久就能下載好的文件剩拢。這里以picjumbo里的一張圖片為例子线得。

NSData方式

其實(shí)我們經(jīng)常用的[NSData dataWithContentsOfURL] 就是一種文件下載方式,猜測(cè)這里面應(yīng)該是發(fā)送了Get請(qǐng)求徐伐。

NSURL *url = [NSURL URLWithString:@"https://picjumbo.imgix.net/HNCK8461.jpg?q=40&w=1650&sharp=30"];
NSData *data = [NSData dataWithContentsOfURL:url];

當(dāng)然下載代碼應(yīng)該放到子線程執(zhí)行

NSURLConnection方式下載

NSURL* url = [NSURL URLWithString:@"https://picjumbo.imgix.net/HNCK8461.jpg?q=40&w=1650&sharp=30"];
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

self.imageView.image = [UIImage imageWithData:data];
    }];

就是發(fā)送一個(gè)異步的Get請(qǐng)求贯钩,回調(diào)的data就是我們下載到的圖片。

大文件下載

NSURLConnection下載

通過(guò)上面的兩個(gè)方法去下載大文件是不合理的办素,因?yàn)檫@兩個(gè)方法都是一次性返回整個(gè)下載到的文件角雷,返回的data在內(nèi)存中,如果下載一個(gè)幾百兆的東西摸屠,內(nèi)存肯定會(huì)爆的谓罗。
其實(shí)NSURLConnection還提供了另外一種發(fā)送請(qǐng)求的方式
// 發(fā)送請(qǐng)求去下載 (創(chuàng)建完conn對(duì)象后,會(huì)自動(dòng)發(fā)起一個(gè)異步請(qǐng)求)

[NSURLConnection connectionWithRequest:request delegate:self];

這里用到了代理季二,那肯定要遵守協(xié)議了.遵守NSURLConnectionDataDelegate 協(xié)議.
進(jìn)去看看有幾個(gè)代理方法檩咱,其實(shí)我們能用到的也就三個(gè)揭措。

/**
 *  請(qǐng)求失敗時(shí)調(diào)用(請(qǐng)求超時(shí)、網(wǎng)絡(luò)異常)
 *
 *  @param error      錯(cuò)誤原因
 */
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{

}
/**
 *  1.接收到服務(wù)器的響應(yīng)就會(huì)調(diào)用
 *
 *  @param response   響應(yīng)
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{

}
/**
 *  2.當(dāng)接收到服務(wù)器返回的實(shí)體數(shù)據(jù)時(shí)調(diào)用(具體內(nèi)容刻蚯,這個(gè)方法可能會(huì)被調(diào)用多次)
 *
 *  @param data       這次返回的數(shù)據(jù)
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{

}
/**
 *  3.加載完畢后調(diào)用(服務(wù)器的數(shù)據(jù)已經(jīng)完全返回后)
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{

}

通過(guò)執(zhí)行下載操作绊含,分別log上面三個(gè)方法,會(huì)發(fā)現(xiàn)didReceiveData這個(gè)方法會(huì)被頻繁的調(diào)用炊汹,每次都會(huì)傳回來(lái)一部分data躬充,下面是官方api對(duì)這個(gè)方法的說(shuō)明

is called with a single immutable NSData object to the delegate,
representing the next portion of the data loaded from the connection. This is the only guaranteed for the delegate to receive the data from the resource load.

由此我們可以知道,這種下載方式是通過(guò)這個(gè)代理方法每次傳回來(lái)一部分文件讨便,最終我們把每次傳回來(lái)的數(shù)據(jù)合并成一個(gè)我們需要的文件充甚。
這時(shí)候我們通常想到的方法是定義一個(gè)全局的NSMutableData,接受到響應(yīng)的時(shí)候初始化這個(gè)MutableData,在didReceiveData方法里面去拼接

[self.totalData appendData:data];

最后在完成下載的方法里面吧整個(gè)MutableData寫入沙盒霸褒。
代碼如下:

@property (weak, nonatomic) IBOutlet UIProgressView *myPregress;

@property (nonatomic,strong) NSMutableData* fileData;

/**
 *  文件的總長(zhǎng)度
 */
@property (nonatomic, assign) long long totalLength;
/**
 *  1.接收到服務(wù)器的響應(yīng)就會(huì)調(diào)用
 *
 *  @param response   響應(yīng)
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
![20150908141106978.png](http://upload-images.jianshu.io/upload_images/5145760-5af285edcb25ceb7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    self.fileData = [NSMutableData data];
    // 獲取要下載的文件的大小
    self.totalLength = response.expectedContentLength;
}
/**
 *  2.當(dāng)接收到服務(wù)器返回的實(shí)體數(shù)據(jù)時(shí)調(diào)用(具體內(nèi)容伴找,這個(gè)方法可能會(huì)被調(diào)用多次)
 *
 *  @param data       這次返回的數(shù)據(jù)
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.fileData appendData:data];
    self.myPregress.progress = (double)self.fileData.length / self.totalLength;
}
/**
 *  3.加載完畢后調(diào)用(服務(wù)器的數(shù)據(jù)已經(jīng)完全返回后)
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // 拼接文件路徑
    NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *file = [cache stringByAppendingPathComponent:response.suggestedFilename];

    // 寫到沙盒中
    [self.fileData writeToFile:file atomically:YES];
}

我這里下載的是javajdk。(度娘的地址)
注意:通常大文件下載是需要給用戶展示下載進(jìn)度的废菱。
這個(gè)數(shù)值是 已經(jīng)下載的數(shù)據(jù)大小/要下載的文件總大小
已經(jīng)下載的數(shù)據(jù)我們可以記錄技矮,要下載的文件總大小在服務(wù)器返回的響應(yīng)頭里面可以拿到,在接受到響應(yīng)的方法里執(zhí)行

 NSHTTPURLResponse *res = (NSHTTPURLResponse*)response;

    NSDictionary *headerDic = res.allHeaderFields;
    NSLog(@"%@",headerDic);
    self.fileLength = [[headerDic objectForKey:@"Content-Length"] intValue];

不得不說(shuō)蘋果太為開發(fā)者考慮了殊轴,我們不必這么麻煩的去獲取文件總大小了衰倦,
response.expectedContentLength 這句代碼就搞定了。
response.suggestedFilename 這句代表獲取下載的文件名

20150908141106978.png

題外話扯的有點(diǎn)多旁理,言歸正傳樊零,這樣我們確實(shí)可以下載文件,最后拿到的文件也能正常運(yùn)行

20150908141855072.png

但是有個(gè)致命的問(wèn)題韧拒,內(nèi)存淹接!用來(lái)接受文件的NSMutableData一直都在內(nèi)存中,會(huì)隨著文件的下載一直變大叛溢,

20150908142050348.png

所有這種處理方式絕對(duì)是不合理的塑悼。
合理的方式在我們獲取一部分data的時(shí)候就寫入沙盒中,然后釋放內(nèi)存中的data楷掉。
這里要用到NSFilehandle這個(gè)類厢蒜,這個(gè)類可以實(shí)現(xiàn)對(duì)文件的讀取、寫入烹植、更新斑鸦。
下面總結(jié)了一些常用的NSFileHandle的方法,在這個(gè)表中草雕,fh是一個(gè)NSFileHandle對(duì)象巷屿,data是一個(gè)NSData對(duì)象,path是一個(gè)NSString 對(duì)象墩虹,offset是易額Unsigned long long變量嘱巾。

20150908144609499.png

具體關(guān)于NSFileHandle的用法各位自行搜索憨琳。
在接受到響應(yīng)的時(shí)候就在沙盒中創(chuàng)建一個(gè)空的文件,然后每次接收到數(shù)據(jù)的時(shí)候就拼接到這個(gè)文件的最后面旬昭,通過(guò)- (unsigned long long)seekToEndOfFile; 這個(gè)方法

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // 文件路徑
    NSString* ceches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString* filepath = [ceches stringByAppendingPathComponent:response.suggestedFilename];

    // 創(chuàng)建一個(gè)空的文件到沙盒中
    NSFileManager* mgr = [NSFileManager defaultManager];
    [mgr createFileAtPath:filepath contents:nil attributes:nil];

    // 創(chuàng)建一個(gè)用來(lái)寫數(shù)據(jù)的文件句柄對(duì)象
    self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath];

    // 獲得文件的總大小
    self.totalLength = response.expectedContentLength;

}
/**
 *  2.當(dāng)接收到服務(wù)器返回的實(shí)體數(shù)據(jù)時(shí)調(diào)用(具體內(nèi)容篙螟,這個(gè)方法可能會(huì)被調(diào)用多次)
 *
 *  @param data       這次返回的數(shù)據(jù)
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // 移動(dòng)到文件的最后面
    [self.writeHandle seekToEndOfFile];

    // 將數(shù)據(jù)寫入沙盒
    [self.writeHandle writeData:data];

    // 累計(jì)寫入文件的長(zhǎng)度
    self.currentLength += data.length;

    // 下載進(jìn)度
    self.myPregress.progress = (double)self.currentLength / self.totalLength;
}
/**
 *  3.加載完畢后調(diào)用(服務(wù)器的數(shù)據(jù)已經(jīng)完全返回后)
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    self.currentLength = 0;
    self.totalLength = 0;

    // 關(guān)閉文件
    [self.writeHandle closeFile];
    self.writeHandle = nil;
}

這樣在下載過(guò)程中內(nèi)存就會(huì)一直很穩(wěn)定了,并且下載的文件也是沒(méi)問(wèn)題的问拘。

20150908150738080.png

斷點(diǎn)下載

暫停/繼續(xù)下載也是現(xiàn)在下載中必備的功能了遍略,如果沒(méi)有暫停功能,用戶體驗(yàn)相比會(huì)很差骤坐,而且如果突然網(wǎng)絡(luò)不好中斷了绪杏,沒(méi)有實(shí)現(xiàn)斷點(diǎn)下載的話只有重新下了。或油。寞忿。
下面讓我們來(lái)加入斷點(diǎn)下載功能吧。
NSURLConnection 只提供了一個(gè)cancel方法顶岸,這并不是暫停,而是取消下載任務(wù)叫编。如果要實(shí)現(xiàn)斷點(diǎn)下載必須要了解HTTP協(xié)議中請(qǐng)求頭的Range辖佣。

20150908155815582.png

不難看出,通過(guò)設(shè)置請(qǐng)求頭的Range我們可以指定下載的位置搓逾、大小卷谈。
那么我們這樣設(shè)置bytes=500- 從500字節(jié)以后的所有字節(jié),
只需要在didReceiveData中記錄已經(jīng)寫入沙盒中文件的大小(self.currentLength)霞篡,
把這個(gè)大小設(shè)置到請(qǐng)求頭中世蔗,因?yàn)榈谝淮蜗螺d肯定是沒(méi)有執(zhí)行過(guò)didReceive方法,self.currentLength也就為0朗兵,也就是從頭開始下污淋。
上代碼:

#pragma mark --按鈕點(diǎn)擊事件

- (IBAction)btnClicked:(UIButton *)sender {

    // 狀態(tài)取反
    sender.selected = !sender.isSelected;

    // 斷點(diǎn)續(xù)傳
    // 斷點(diǎn)下載

    if (sender.selected) { // 繼續(xù)(開始)下載
        // 1.URL
        NSURL *url = [NSURL URLWithString:@"http://localhost:8080//term_app/hdgg.zip"];

        // 2.請(qǐng)求
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

        // 設(shè)置請(qǐng)求頭
        NSString *range = [NSString stringWithFormat:@"bytes=%lld-", self.currentLength];
        [request setValue:range forHTTPHeaderField:@"Range"];

        // 3.下載
        self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
    } else { // 暫停

        [self.connection cancel];
        self.connection = nil;
    }
}

在下載過(guò)程中,為了提高效率余掖,充分利用cpu性能寸爆,通常會(huì)執(zhí)行多線程下載,代碼就不貼了盐欺,分析一下思路:
下載開始赁豆,創(chuàng)建一個(gè)和要下載的文件大小相同的文件(如果要下載的文件為100M,那么就在沙盒中創(chuàng)建一個(gè)100M的文件冗美,然后計(jì)算每一段的下載量魔种,開啟多條線程下載各段的數(shù)據(jù),分別寫入對(duì)應(yīng)的文件部分)粉洼。

NSURLSession下載方式

上面這種下載文件的方式確實(shí)比較復(fù)雜节预,要自己去控制內(nèi)存寫入相應(yīng)的位置甲抖,不過(guò)在蘋果在iOS7推出了一個(gè)新的類NSURLSession,它具備了NSURLConnection所具備的方法,同時(shí)也比它更強(qiáng)大心铃。蘋果推出它的目的大有取代NSURLConnection的趨勢(shì)或者目的准谚。
NSURLSession 也可以發(fā)送Get/Post請(qǐng)求,實(shí)現(xiàn)文件的下載和上傳去扣。
在NSURLSesiion中柱衔,任何請(qǐng)求都可以被看做是一個(gè)任務(wù)。其中有三種任務(wù)類型

// NSURLSessionDataTask : 普通的GET\POST請(qǐng)求
// NSURLSessionDownloadTask : 文件下載
// NSURLSessionUploadTask : 文件上傳(很少用愉棱,一般服務(wù)器不支持)

NSURLSession 簡(jiǎn)單使用

NSURLSession發(fā)送請(qǐng)求非常簡(jiǎn)單唆铐,與connection不同的是,任務(wù)創(chuàng)建后不會(huì)自動(dòng)發(fā)送請(qǐng)求奔滑,需要手動(dòng)開始執(zhí)行任務(wù)艾岂。

 // 1.得到session對(duì)象
    NSURLSession* session = [NSURLSession sharedSession];
    NSURL* url = [NSURL URLWithString:@""];

    // 2.創(chuàng)建一個(gè)task,任務(wù)
    NSURLSessionDataTask* dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        // data 為返回?cái)?shù)據(jù)
    }];

    // 3.開始任務(wù)
    [dataTask resume];
// 發(fā)送post請(qǐng)求 自定義請(qǐng)求頭
[session dataTaskWithRequest:<#(NSURLRequest *)#> completionHandler:<#^(NSData *data, NSURLResponse *response, NSError *error)completionHandler#>]

NSURLSession 下載

使用NSURLSession就非常簡(jiǎn)單了朋其,不需要去考慮什么邊下載邊寫入沙盒的問(wèn)題王浴,蘋果都幫我們做好了。代碼如下

 NSURL* url = [NSURL URLWithString:@"http://dlsw.baidu.com/sw-search-sp/soft/9d/25765/sogou_mac_32c_V3.2.0.1437101586.dmg"];

    // 得到session對(duì)象
    NSURLSession* session = [NSURLSession sharedSession];

    // 創(chuàng)建任務(wù)
    NSURLSessionDownloadTask* downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

    }];
    // 開始任務(wù)
    [downloadTask resume];

是不是跟NSURLConnection很像梅猿,但仔細(xì)看會(huì)發(fā)現(xiàn)回調(diào)的方法里面并沒(méi)用NSData傳回來(lái)氓辣,多了一個(gè)location,顧名思義袱蚓,location就是下載好的文件寫入沙盒的地址钞啸,打印一下發(fā)現(xiàn)下載好的文件被自動(dòng)寫入的temp文件夾下面了。
location:file:///Users/yeaodong/Library/Developer/CoreSimulator/Devices/E52B4B95-53E1-46A2-9881-8C969958FBC0/data/Containers/Data/Application/BFB9F0CA-0F50-4682-BBBD-B71B54C39EBE/tmp/CFNetworkDownload_YNnuIS.tmp

20150910155745812.png

不過(guò)在下載完成之后會(huì)自動(dòng)刪除temp中的文件喇潘,所有我們需要做的只是在回調(diào)中把文件移動(dòng)(或者復(fù)制体斩,反正之后會(huì)自動(dòng)刪除)到caches中。

NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        // response.suggestedFilename : 建議使用的文件名颖低,一般跟服務(wù)器端的文件名一致
        NSString *file = [caches stringByAppendingPathComponent:response.suggestedFilename];

        // 將臨時(shí)文件剪切或者復(fù)制Caches文件夾
        NSFileManager *mgr = [NSFileManager defaultManager];

        // AtPath : 剪切前的文件路徑
        // ToPath : 剪切后的文件路徑
        [mgr moveItemAtPath:location.path toPath:file error:nil];

不過(guò)通過(guò)這種方式下載有個(gè)缺點(diǎn)就是無(wú)法監(jiān)聽下載進(jìn)度絮吵,要監(jiān)聽下載進(jìn)度,蘋果通常的作法是通過(guò)delegate枫甲,這里也一樣源武。而且NSURLSession的創(chuàng)建方式也有所不同。
首先遵守協(xié)議<NSURLSessionDownloadDelegate> 注意不要寫錯(cuò)
點(diǎn)進(jìn)去發(fā)現(xiàn)協(xié)議里面有三個(gè)方法想幻。

#pragma mark -- NSURLSessionDownloadDelegate
/**
 *  下載完畢會(huì)調(diào)用
 *
 *  @param location     文件臨時(shí)地址
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
}
/**
 *  每次寫入沙盒完畢調(diào)用
 *  在這里面監(jiān)聽下載進(jìn)度粱栖,totalBytesWritten/totalBytesExpectedToWrite
 *
 *  @param bytesWritten              這次寫入的大小
 *  @param totalBytesWritten         已經(jīng)寫入沙盒的大小
 *  @param totalBytesExpectedToWrite 文件總大小
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    self.pgLabel.text = [NSString stringWithFormat:@"下載進(jìn)度:%f",(double)totalBytesWritten/totalBytesExpectedToWrite];
}

/**
 *  恢復(fù)下載后調(diào)用,
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{

}

這上面的注釋已經(jīng)很詳細(xì)了闹究,相信大家都能看懂吧。
NSURLSession創(chuàng)建方式,這里就不能使用Block回調(diào)方式了食店,如果給下載任務(wù)設(shè)置了completionHandler這個(gè)block嗅定,也實(shí)現(xiàn)了下載的代理方法用踩,優(yōu)先執(zhí)行block渠退,代理方法也就不會(huì)執(zhí)行了。

// 得到session對(duì)象
    NSURLSessionConfiguration* cfg = [NSURLSessionConfiguration defaultSessionConfiguration]; // 默認(rèn)配置

    NSURLSession* session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    // 創(chuàng)建任務(wù)
    NSURLSessionDownloadTask* downloadTask = [session downloadTaskWithURL:url];

    // 開始任務(wù)
    [downloadTask resume];

相比之前的NSURLConnection方式簡(jiǎn)單很多吧脐彩,用NSURLSessionDownloadTask做斷點(diǎn)下載也很簡(jiǎn)單碎乃,我們先了解一下任務(wù)的取消方法

- (void)cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler;

取消操作以后會(huì)調(diào)用一個(gè)Block,并傳入一個(gè)resumeData惠奸,該參數(shù)包含了繼續(xù)下載文件的位置信息梅誓。也就是說(shuō),當(dāng)你下載了10M得文件數(shù)據(jù)佛南,暫停了梗掰。那么你下次繼續(xù)下載的時(shí)候是從第10M這個(gè)位置開始的,而不是從文件最開始的位置開始下載共虑。因而為了保存這些信息愧怜,所以才定義了這個(gè)NSData類型的這個(gè)屬性:resumeData。這個(gè)data只包含了url跟已經(jīng)下載了多少數(shù)據(jù)妈拌,不會(huì)很大,不用擔(dān)心內(nèi)存問(wèn)題蓬蝶。
另外,session還提供了通過(guò)resumeData來(lái)創(chuàng)建任務(wù)的方法

- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;

我們只需要在取消操作的回調(diào)中記錄好resumeData尘分,然后在恢復(fù)下載的適合通過(guò)上面的方法創(chuàng)建任務(wù)就好了,相比NSURLconnection簡(jiǎn)單太多了丸氛。
需要注意的是Block中循環(huán)引用的問(wèn)題

__weak typeof(self) selfVc = self;
    [self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
        selfVc.resumeData = resumeData;
        selfVc.downloadTask = nil;
    }];

示例程序下載:https://github.com/hongfenglt/HFDownLoad

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末培愁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缓窜,更是在濱河造成了極大的恐慌定续,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件禾锤,死亡現(xiàn)場(chǎng)離奇詭異私股,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)恩掷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門倡鲸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人黄娘,你說(shuō)我怎么就攤上這事峭状】说危” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵优床,是天一觀的道長(zhǎng)劝赔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)胆敞,這世上最難降的妖魔是什么着帽? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮竿秆,結(jié)果婚禮上启摄,老公的妹妹穿的比我還像新娘。我一直安慰自己幽钢,他們只是感情好歉备,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著匪燕,像睡著了一般檐束。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上畜疾,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天囊榜,我揣著相機(jī)與錄音,去河邊找鬼尼变。 笑死利凑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嫌术。 我是一名探鬼主播哀澈,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼度气!你這毒婦竟也來(lái)了割按?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤磷籍,失蹤者是張志新(化名)和其女友劉穎适荣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體院领,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弛矛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栅盲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汪诉。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出扒寄,到底是詐尸還是另有隱情鱼鼓,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布该编,位于F島的核電站迄本,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏课竣。R本人自食惡果不足惜嘉赎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望于樟。 院中可真熱鬧公条,春花似錦、人聲如沸迂曲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)路捧。三九已至关霸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杰扫,已是汗流浹背队寇。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留章姓,地道東北人佳遣。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凡伊,于是被迫代替她去往敵國(guó)和親苍日。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容