网络编程—NSURLSession

文艺求关注.png

okay,NSURLConnection在iOS9.0之后已经被废弃掉了,当然我们在开发中不免会遇到一些NSURLConnection的代码,到时候知道如何处理就Ok了,我们的重点是要好好聊心啊NSURLSession

<h5>NSURLSession</h5>

  • 使用步骤:
    • 使用NSURLSession对象创建Task,然后执行Task
    • Task的类型


      Task的类型.png

<h5>NSURLSessionDataTask</h5>

  • 使用NSURLSession比NSURLConnection多几个步骤

<b>1.发送GET请求</b>

- (void)sessionSendRequestWithGet {

    // 01.创建请求路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
    
    // 02.创建请求对象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    // 03.创建会话对象(单例模式获取,还有一种方法创建会话对象:自定义Session,等下会讲)
    NSURLSession *session = [NSURLSession sharedSession];
    
    /**
     // 04.创建Task
     
     @param NSURL 请求对象
     @param completionHandler 当请求完成的时候调用
        data:响应体信息
        response:响应头信息
        error:错误信息当请求失败的时候 error有值
     */
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"-----%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    // 05.执行Task
    [dataTask resume];
}

- (void)dealloc {
    // 清理方法
    [self.session invalidateAndCancel];
}
  • <b>*注意:04创建dataTask的时候还有一种简单方法(不需要设置请求对象,直接传URL)的方法</b>
    //*注意:dataTaskWithURL 内部会自动的将请求路径作为参数创建一个请求对象(即不可变只能发GET请求)
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"-----%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];

<b>2.发送POST请求</b>

- (void)sessionSendRequestWithPost {

    // 01.确定URL
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
    // 02.创建可变的请求对象
    NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:url];
    
    // 2.1设置请求方式为POST
    mutableRequest.HTTPMethod = @"POST";
    
    // 2.2设置请求体
    mutableRequest.HTTPBody = [@"username=123&pwd=123&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
    // 03.创建会话对象
    NSURLSession *session = [NSURLSession sharedSession];
    
    // 04.创建Task
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:mutableRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        //该Block在子线程中调用,
        NSLog(@"%@", [NSThread currentThread]);
        
        // 06.解析数据
        NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    // 05.执行Task
    [dataTask resume];
}

- (void)dealloc {
    // 清理方法
    [self.session invalidateAndCancel];
}

<b>3.NSURLSession的代理方法</b>

- (void)sessionUsedWithDelegate {

    // 01.确定URL
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"];
    
    // 02.创建请求对象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    /**
     // 03.创建会话对象(使用代理方法)
     @param NSURLSessionConfiguration 配置信息
     @param NSURLSessionDelegate 代理
     @param NSOperationQueue 设置代理在哪个线程中调用
     */
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    // 04.创建Task
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
    
    // 05.执行task
    [dataTask resume];
}
@property (nonatomic, strong) NSString *fullPath;
@property (nonatomic, strong) NSFileHandle *fileHandle;
@property (nonatomic, assign) NSInteger totalSize;
@property (nonatomic, assign) NSInteger currentSize;

@property (weak, nonatomic) IBOutlet UIProgressView *progressView;  // 显示文件下载进度
#pragma mark - NSURLSessionDataDelegate
/**
 // 接收到服务器的响应时调用 它默认会取消该请求
 @param session 会话信息
 @param dataTask 请求任务
 @param response 响应头信息
 @param completionHandler 回调 传给系统的
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
    // 获得文件的总大小
    self.totalSize = response.expectedContentLength;
    
    //1.获得文件路径
    self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
    
    // 创建一个空的文件
    [[NSFileManager defaultManager] createFileAtPath:self.fullPath contents:nil attributes:nil];
    
    // 创建文件句柄
    self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
    NSLog(@"%s", __func__);
    /**
     NSURLSessionResponseCancel = 0,            取消 默认
     NSURLSessionResponseAllow = 1,              接受
     NSURLSessionResponseBecomeDownload = 2,     变成下载任务
     NSURLSessionResponseBecomeStream            下载任务
     */
    completionHandler(NSURLSessionResponseAllow);  // 特别注意不能遗漏这一点
}
/**
 // 接受服务器返回的数据 调用多次
 @param session 会话信息
 @param dataTask 请求任务
 @param data 本次下载的数据
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {

    NSLog(@"%s", __func__);
    
    // 写入数据
    [self.fileHandle writeData:data];
    
    // 计算文件的下载进度
    self.currentSize += data.length;
    NSLog(@"%f", 1.0 * self.currentSize / self.totalSize);
    self.progressView.progress = 1.0 * self.currentSize / self.totalSize;

}
/**
 // 请求结束或者失败的时候调用该方法,
 @param session 会话对象
 @param task 请求任务
 @param error 错误信息
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

    NSLog(@"%s", __func__);
    
    // 关闭文件句柄
    [self.fileHandle closeFile];
    self.fileHandle = nil;
}

- (void)dealloc {
    // 清理方法
    [self.session invalidateAndCancel];
}

<h5>NSURLSessionDownloadTask</h5>

  • downloadTask文件下载(优点:无需担心内存问题—子线程完成,缺点,无法监听下载进度)
- (void)downloadWithDownloadTask {
    
    // 01.确定路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"];
    
    // 02.创建请求对象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    // 03.创建会话对象
    NSURLSession *session = [NSURLSession sharedSession];
    /**
     // 04.创建下载任务(downloadTask)

     @param NSURLRequest 请求对象
     @param completionHandler 回调
        location: 文件保存临时沙盒路径
        response: 响应头信息
        error: 错误信息
     */
    // 注意:该方法内部已经实现了遍下载数据,遍写入沙盒(tmp)的操作,
    // 缺点:无法监听下载进度
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        // 06.解析数据
        NSLog(@"%@------%@---", location, [NSThread currentThread]);  // 子线程中完成
        // 6.1拼接文件的全路径
        // 方法一:
        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:url.lastPathComponent]; //url.lastPathComponent: 获得URL最后的字节为为文件的名称

        // 方法二:
        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
        // 6.2剪切文件
        [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
    }];
    
    // 05.执行下载任务
    [downloadTask resume];
}
  • downloadTask通过代理实现文件下载(可监听文件下载进度)
- (void)downloadTaskWithDelegate {
    
    // 01.确定路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"];
    
    // 02.创建请求对象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    // 03.创建会话对象并设置代理
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    // 04.创建downloadTask
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
    // 05.执行下载任务
    [downloadTask resume];  
}
<NSURLSessionDownloadDelegate>

#pragma mark - NSURLSessionDownloadDelegate
/**
 写数据
 @param session 会话对象
 @param downloadTask 下载任务
 @param bytesWritten 本次写入的数据大小
 @param totalBytesWritten 下载数据的总大小
 @param totalBytesExpectedToWrite 文件总大小(期望大小)
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    
    // 1.获得文件的下载进度
    NSLog(@"%f", 1.0 * totalBytesWritten / totalBytesExpectedToWrite);

}
/**
 当恢复下载的时候调用
 @param session 会话对象
 @param downloadTask 下载任务
 @param fileOffset 从什么地方开始下载
 @param expectedTotalBytes 文件总大小
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {

    NSLog(@"%zd", __func__);
}
/**
 当下载完成的时候调用
 @param session 会话对象
 @param downloadTask 下载任务
 @param location 文件临时存储路径
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {

    NSLog(@"%@", location);
    
    // 1.拼接文件的全路径
    NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
    
    // 2.剪切文件
    [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
}
/**
 请求结束调用
 @param session 会话对象
 @param task 下载任务
 @param error 错误信息
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

    NSLog(@"didCompleteWithError");
}

- (void)dealloc {

    // 清理方法一
    [self.session finishTasksAndInvalidate];
}

需求:如何使用NSURLSessionDataTask实现断点离线续传下载,

@property (nonatomic, strong) NSURLSessionDataTask *dataTask;
@property (nonatomic, assign) NSInteger currentSize;
#pragma mark - lazy load
- (NSURLSessionDataTask *)dataTask {

    if (_dataTask == nil) {
        // 01.确定URL
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_05.mp4"];
        
        // 02.创建请求对象
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        
        // 2.1设置请求头信息,告诉服务器请求哪一部分数据
        self.currentSize = [self getFileSize];
        //设置请求的数据范围
        /*
         bytes=0-100
         bytes=500-1000
         bytes=-100 请求文件的前100个字节
         bytes=500-
         */
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-", self.currentSize];
        [request setValue:range forHTTPHeaderField:@"Range"];
        
        // 04.创建DataTask任务
        _dataTask = [self.session dataTaskWithRequest:request];
    }
    return _dataTask;
}
@property (nonatomic, strong) NSDictionary *fileInfoDic;
- (NSInteger) getFileSize {
    // 2.1获得指定文件路径对应的文件数据大小
    self.fileInfoDic = [[NSFileManager defaultManager] attributesOfItemAtPath:self.fullPath error:nil];
    NSLog(@"%@", self.fileInfoDic);
    NSInteger currentSize = [self.fileInfoDic[@"NSFileSize"] integerValue];
    return currentSize;
}
@property (nonatomic, strong) NSString *fullPath;
#pragma mark - lazy load
- (NSString *)fullPath {
    
    if (_fullPath == nil) {
        
        // 01.获得文件的全路径
        _fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:FileName];
    }
    return _fullPath;
}
@property (nonatomic, strong) NSURLSession *session;
#pragma mark - lazy load
- (NSURLSession *)session {

    if (_session == nil) {
        
        // 03.创建会话对象
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}
// 在storyboard中添加按钮,分别命名:开始下载、暂停下载、继续下载、取消下载,并拖线

#pragma mark - method
- (IBAction)startDownloadBtnClick:(id)sender {
    
    NSLog(@"+++++++++++++++++++++++ start +++");
    // 执行dataTask
    [self.dataTask resume];
}
- (IBAction)suspendDownloadBtnClick:(id)sender {
    
    NSLog(@"+++++++++++++++++++++++ suspend +++");
    [self.dataTask suspend];
}
- (IBAction)continueDownloadBtnClick:(id)sender {
    
    NSLog(@"+++++++++++++++++++++++ continue +++");
    [self.dataTask resume];
}
- (IBAction)cancelDownloadBtnClick:(id)sender {
    
    NSLog(@"+++++++++++++++++++++++ cancel +++");
    // 此取消不可以恢复
    [self.dataTask cancel];
    self.dataTask = nil;
}
#pragma mark - property
@property (weak, nonatomic) IBOutlet UIProgressView *progerssView;  //进度条
@property (nonatomic, assign) NSInteger totalSize;
@property (nonatomic, strong) NSString *filePath;
@property (nonatomic, strong) NSFileHandle *fileHandle;

#pragma mark - NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {

    // *1.获得文件的总大小 本次请求数据的大小
    self.totalSize = response.expectedContentLength + self.currentSize;
   
    // - 01/ 将文件总大小写入到磁盘
    [[[NSString stringWithFormat:@"%zd", self.totalSize] dataUsingEncoding:NSUTF8StringEncoding] writeToFile:SizeOfFullPath atomically:YES];
    
   
    if (self.currentSize == 0) {
        // 02.创建一个空的文件
        [[NSFileManager defaultManager] createFileAtPath:self.fullPath contents:nil attributes:nil];
    }
    
    // 03.创建文件句柄
    self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
    [self.fileHandle seekToEndOfFile];  //移动文件句柄到文件末尾
    
    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {

    // 04.写入数据
    [self.fileHandle writeData:data];
    
    // *2.计算下载进度
    self.currentSize += data.length;
    NSLog(@"%f", 1.0 * self.currentSize / self.totalSize);
    self.progerssView.progress = 1.0 * self.currentSize / self.totalSize;
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

    // 05.关闭文件句柄
    [self.fileHandle closeFile];
    self.fileHandle = nil;
    NSLog(@"%@", self.fullPath);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // - 02/ 获得之前已经下载的文件数据大小 => 获得沙盒中已经存在的数据大小
    // 获得某个路径对象的属性
    self.fileInfoDic = [[NSFileManager defaultManager] attributesOfItemAtPath:self.fullPath error:nil];
    
    self.currentSize = [self.fileInfoDic fileSize];
    
    NSLog(@"之前已经下载的数据大小:%zd", self.currentSize);
    
    // - 03/ 显示文件的进度信息 = 已经下载文件数据大小(self.currentSize)/ 文件总大小
    NSData *totalData = [NSData dataWithContentsOfFile:SizeOfFullPath];
    self.totalSize = [[[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding] integerValue];
    
    // - 04/ 判断当前文件大小是否为0
    if (self.totalSize != 0) {
        self.progerssView.progress = 1.0 * self.currentSize / self.totalSize;
    }  
}

- (void)dealloc {

    // 清理方法
    [self.session invalidateAndCancel];
}

<h5>NSURLSession对象的释放</h5>

与NSURLConnection不一样的地方,NSURLSession在不用的时候需要手动将session对象释放

- (void)dealloc {

    // 清理方法一
    [self.session finishTasksAndInvalidate];

    // 清理方法二
    [self.session invalidateAndCancel];
}

<h5>使用NSURLSession完成上传任务</h5>

- (void)uploadWithSession02 {
    
    // 01确定URL
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
    
    // 02创建可变的请求对象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    // 2.1设置请求方法
    request.HTTPMethod = @"POST";
    
    // 2.2设置请求头信息
    //+ "设置请求头信息 Content-Type multipart/form-data; boundary=----WebKitFormBoundaryhGFJfxbHklxi7PXJ
    NSString *headerString = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary];
    [request setValue:headerString forHTTPHeaderField:@"Content-Type"];
 
    /**
     // 04创建uploadTask
     @param NSURLRequest 请求对象
     @param NSURLResponse 传递上传的数据(请求体)
     */
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:[self getBodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        // 06.解析
        NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);      
    }];
    
    // 05执行uploadTask
    [uploadTask resume];
}
@property (nonatomic, strong) NSURLSession *session;
// 在开发中会将session抽出来,懒加载同时设置配置信息
- (NSURLSession *)session {
    if (_session == nil) {
        // 03.设置会话对象
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration  defaultSessionConfiguration];
        _session = [NSURLSession sessionWithConfiguration: configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}
// 拼接请求体信息,与NSURLConnection一样,上传文件的时候都需要设置请求头和请求体信息
-(NSData *)getBodyData
{
    NSMutableData *fileData = [NSMutableData data];
    
    //① 文件参数
    /*
     --分隔符
     Content-Disposition: form-data; name="file"; filename="Snip20161012_16.png"
     Content-Type: image/png
     空行
     图片的二进制数据
     */
    [fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];
    //name=file        参数(固定的 服务器端规定)
    //filename=123.png 该文件上传到服务器后以什么名称保存
    [fileData appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"Sss.png\"" dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];
    
    //Content-Type 上传给服务器的文件的数据类型(MIMEType)
    [fileData appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];
    [fileData appendData:KNewLine];
    NSData *data = [NSData dataWithContentsOfFile:@"/Users/Vincent/Desktop/3.pic"];
    [fileData appendData:data];
    [fileData appendData:KNewLine];
    
    
    //②非文件参数
    /*
     --分隔符
     Content-Disposition: form-data; name="username"
     空行
     xiaoming
     */
    [fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];
    //name=username 参数名 usernmae|pwd
    [fileData appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];
    [fileData appendData:KNewLine];
    [fileData appendData:[@"xiaomingHeXiaohong" dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];
    
    //③ 结尾标志
    /*
     --分隔符--
     */
    [fileData appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
    return fileData;
}

#pragma mark - NSURLSessionDataDelegate
/**
 @param session 会话对象
 @param task 上传任务
 @param bytesSent 表示本次上传的数据
 @param totalBytesSent 上传完成数据的大小
 @param totalBytesExpectedToSend 文件的总大小
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
    
    // 监听下载进度
    NSLog(@"%f", 1.0 * totalBytesSent / totalBytesExpectedToSend);
}

关注一下又不会怀孕.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356

推荐阅读更多精彩内容