JS關(guān)于文件的處理

Blob

Blob虏杰,Binary Large Object的縮寫讥蟆,代表二進(jìn)制類型的大對(duì)象。Mysql中的Blob類型就表示二進(jìn)制數(shù)據(jù)的容器嘹屯,在Web中攻询,Blob對(duì)象是二進(jìn)制數(shù)據(jù),但它是類似文件對(duì)象的二進(jìn)制數(shù)據(jù)州弟,因此可以操作File對(duì)象一樣操作Blob對(duì)象钧栖,實(shí)際上低零,F(xiàn)ile繼承自Blob

Blob、File拯杠、ArrayBuffer掏婶、FileList、FileReader潭陪、DataURL雄妥、BlobURL

  • Blob和ArrayBuffer都是用來(lái)存儲(chǔ)二進(jìn)制的,Blob是對(duì)象依溯,ArrayBuffer是數(shù)組老厌,由于ArrayBuffer是一個(gè)二進(jìn)制數(shù)組,所以可以作為Blob對(duì)象的參數(shù):
//為<div> hello world</div>的二進(jìn)制
const u8Buf = new Uint8Array([60, 100, 105, 118, 62, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 60, 47, 100, 105, 118, 62]);
const u8Blob = new Blob([u8Buf], { type: "text/html" }); // Blob {size: 22, type: "text/html"}
  • ArrayBuffer不能直接操作黎炉,依賴于TypedArray視圖(例如上面的Uint8Array)或者DataView對(duì)象來(lái)解釋原始緩沖區(qū)枝秤。
  • Blob對(duì)象可以直接通過(guò)slice進(jìn)行內(nèi)容分片,其本身只有size和type屬性慷嗜。
  • File對(duì)象繼承于Blob對(duì)象淀弹,并提供了name(文件名)、size(大小)庆械、type(MIME類型)薇溃、lastModified、lastModifiedDate等信息缭乘。
  • FileReader用于異步讀取文件內(nèi)容(用于讀取File沐序、Blob的內(nèi)容)
    • FileReader.readAsArrayBuffer(blob):開始讀取指定Blob中的內(nèi)容,一旦完成忿峻,result屬性中保存的數(shù)據(jù)是被讀取文件的ArrayBuffer數(shù)據(jù)薄啥。(將blob轉(zhuǎn)換成ArrayBuffer)
    • FileReader.readAsBinaryString(blob):開始讀取Blob內(nèi)容,一旦完成逛尚,result屬性中將包含所讀取文件的原始二進(jìn)制數(shù)據(jù)垄惧。
    • FileReader.readAsDataURL(blob):開始讀取指定Blob內(nèi)容,一旦完成绰寞,result屬性中將包含一個(gè)data:URL格式的字符串以表示所讀取文件的內(nèi)容(將blob轉(zhuǎn)換成DataURL到逊,轉(zhuǎn)換成base64編碼)
    • FileReader.readAsText():開始讀取指定Blob內(nèi)容,一旦完成滤钱,result屬性中將包含一個(gè)字符串表示所讀取的文件內(nèi)容
    • FileReader.readyState
      • EMPTY:0 還沒有加載任何數(shù)據(jù)
      • LOADING:1數(shù)據(jù)正在被加載
      • DONE:2已完成全部的讀取請(qǐng)求
    • FileReader.onload:事件觉壶,該事件在讀取操作完成時(shí)觸發(fā)
    • FileRader.onerror:事件,該事件在讀取操作發(fā)生錯(cuò)誤時(shí)觸發(fā)件缸。
  • DataURL由FileReader.readAsDataURL(blob)生成铜靶,為一整串base64編碼是一個(gè)完整的數(shù)據(jù)。BlobURL由window.URL.createObjectURL(blob)生成他炊,是一個(gè)類似于HTTP的URL
  • FileList通常用于表單提交文件時(shí),為文件的類數(shù)組對(duì)象
<body>
    <input type="file" id="file" />
</body>
<script>
    window.onload = function () {
        var fileInput = document.querySelector("#file")
        fileInput.addEventListener("change", function (e) {
            console.log(e.target.files)
            console.log(this.files)
        })
    }
</script>

Blob基本用法

創(chuàng)建

通過(guò)Blob的構(gòu)造函數(shù)創(chuàng)建Blob對(duì)象:

Blob(blobParts[,options])
  • blobParts:為數(shù)組争剿,數(shù)組中的每一項(xiàng)連接起來(lái)構(gòu)成Blob對(duì)象的數(shù)據(jù)已艰,數(shù)組中的每項(xiàng)元素可以是ArrayBuffer,ArrayBufferView,Blob,DOMString蚕苇。
  • options:可選項(xiàng)哩掺,置頂MIME類型和結(jié)束符方式
    • type,默認(rèn)值為 ""涩笤,它代表了將會(huì)被放入到blob中的數(shù)組內(nèi)容的MIME類型嚼吞。
    • endings,默認(rèn)值為"transparent"蹬碧,用于指定包含行結(jié)束符\n的字符串如何被寫入舱禽。 它是以下兩個(gè)值中的一個(gè): "native",表示行結(jié)束符會(huì)被更改為適合宿主操作系統(tǒng)文件系統(tǒng)的換行符恩沽; "transparent"呢蔫,表示會(huì)保持blob中保存的結(jié)束符不變。
    var data1 = "a";
    var data2 = "b";
    var data3 = "<div style='color:red;'>This is a blob</div>";
    var data4 = { "name": "abc" };

    var blob1 = new Blob([data1]);
    var blob2 = new Blob([data1, data2]);
    var blob3 = new Blob([data3]);
    var blob4 = new Blob([JSON.stringify(data4)]);
    var blob5 = new Blob([data4]);
    var blob6 = new Blob([data3, data4]);

    console.log(blob1);  //輸出:Blob {size: 1, type: ""}
    console.log(blob2);  //輸出:Blob {size: 2, type: ""}
    console.log(blob3);  //輸出:Blob {size: 44, type: ""}
    console.log(blob4);  //輸出:Blob {size: 14, type: ""}
    console.log(blob5);  //輸出:Blob {size: 15, type: ""}
    console.log(blob6);  //輸出:Blob {size: 59, type: ""}

size代表Blob對(duì)象中所包含數(shù)據(jù)的字節(jié)數(shù)
使用字符串和使用對(duì)象創(chuàng)建Blob是不同的飒筑,例如blob4通過(guò)JSON.stringify把data4對(duì)象轉(zhuǎn)換成JSON字符串,而blob5則直接使用對(duì)象創(chuàng)建绽昏,兩個(gè)blob對(duì)象的size分別為14和15协屡。
blob4的結(jié)果為"{"name":"abc"}"剛好是14個(gè)字節(jié)。
blob5的記過(guò)為"[object Object]"是15個(gè)字節(jié)全谤。
實(shí)際上肤晓,當(dāng)使用普通對(duì)象創(chuàng)建Blob對(duì)象時(shí),相當(dāng)于調(diào)用了普通對(duì)象的toString()方法得到字符串?dāng)?shù)據(jù)认然,然后在再創(chuàng)建Blob對(duì)象补憾。

slice分片方法

Blob對(duì)象有一個(gè)sloce方法,放回一個(gè)新的Blob對(duì)象卷员,包含了源Blob對(duì)象中范圍內(nèi)的數(shù)據(jù)盈匾。

slice([start[,end[,contentType]]])
  • start:起始下標(biāo),表示第一個(gè)會(huì)被拷貝進(jìn)新的Blob字節(jié)的其實(shí)位置毕骡。如果是一個(gè)負(fù)數(shù)削饵,那么這個(gè)偏移量將會(huì)從數(shù)據(jù)的末尾從后道歉開始計(jì)算。
  • end:結(jié)束下標(biāo)未巫,如果傳入負(fù)數(shù)窿撬,偏移量會(huì)從數(shù)據(jù)的末尾從后到前開始計(jì)算。
  • contentType:新的Blob對(duì)象的文檔類型叙凡,默認(rèn)值為一個(gè)空的字符串劈伴。
var data = "abcdef"
var blob1 = new Blob([data])
var blob2 = blob1.slice(0,3)

//輸出:Blob {size:6,type:""}
console.log(blob1);
//輸出:Blob {size:3,type:""}
console.log(blob2);

Blob使用場(chǎng)景

文件分片上傳

File繼承自Blob,所以我們可以用slice方法對(duì)大文件進(jìn)行分片長(zhǎng)傳

function uploadFile(file){
    //每片大小為1M
    var chunkSize = 1024*1024
    var totalSize = file.size
    //分片總數(shù)
    var chunckQuantity = Math.ceil(totalSize/chunkSize)
    //偏移量
    var offset = 0 
    var reader = new FileReader()
    //設(shè)置文件onload回調(diào)
    reader.onload = function(e){
        var xhr = new XMLHttpRequest()
        xhr.open("POST","http://xxx/upload?fileName="+file.name)
        xhr.overrideMimeType("application/octet-stream")

        xhr.onreadystatechange = function(){
            if(xhr.readState === XMLHttpRequest.DONE && xhr.status === 200){
                ++offset
                if(offset === chunkQuantity){
                    //上傳完成
                }else if(offset === chunckQuantity){
                    //上傳最后一片握爷,偏移量結(jié)束點(diǎn)為文件大小
                    blob = file.slice(offset*chunckSize,totalSize)
                    reader.readAsBinaryString(blob)
                }else{
                    blob = file.slice(offset*chunckSzie,(offset+1)*chunckSize)
                    reader.readAsBinaryString(blob)
                }
            }else{
                alert("上傳出錯(cuò)")
            }
        }
        if(xhr.sendAsBinary){
            //e.target.result為此次讀取的分片二進(jìn)制數(shù)據(jù)
            xhr.sendAsBinary(e.target.result)
        }else{
            xhr.send(e.targt.result)
        }
    }
    var blob = file.slice(0, chunkSize)
    reader.readAsBinaryString(blob)
}

可以進(jìn)一步豐富跛璧,比如上傳進(jìn)度严里,使用多個(gè)XMLHttpRequest對(duì)象并行上傳對(duì)象(需要傳遞分片數(shù)據(jù)的位置參數(shù)給服務(wù)端)等。

Blob URL(資源地址)

Blob URL是Blob協(xié)議的URL:

blob:http://xxx

Blob URL可以通過(guò)URL.createObjectURL(blob)創(chuàng)建赡模,在絕大部分場(chǎng)景下田炭,我們可以像使用HTTP協(xié)議的URL一樣,使用Blob URL漓柑。

常見的場(chǎng)景有:作為文件的下載地址和作為圖片資源地址教硫。

作為文件的下載地址:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Blob Test</title>
    <script>
        function createDownloadFile() {
            var content = "Blob Data";
            var blob = new Blob([content]);
            var link = document.getElementsByTagName("a")[0];
            link.download = "file";
            link.href = URL.createObjectURL(blob);
        }
        window.onload = createDownloadFile;
    </script>
</head>

<body>
    <a>下載</a>
</body>

</html>

點(diǎn)擊下載按鈕,瀏覽器將會(huì)下載一個(gè)名為file的文件辆布,文件內(nèi)容是Blob Data瞬矩。通過(guò)Blob對(duì)象,在前端就可以動(dòng)態(tài)生成文件锋玲,提供瀏覽器下載景用。

image

作為圖片資源地址

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Blob Test</title>
    <script>
        function handleFile(e) {
            var file = e.files[0];
            var blob = URL.createObjectURL(file);
            var img = document.getElementsByTagName("img")[0];
            img.src = blob;
            img.onload = function(e) {
                URL.revokeObjectURL(this.src);  // 釋放createObjectURL創(chuàng)建的對(duì)象##
            }
        }
    </script>
</head>

<body>
    <input type="file" accept="image/*" onchange="handleFile(this)" />
    <br/>
    <img style="width:200px;height:200px">
</body>

</html>

在network標(biāo)簽欄下能夠發(fā)現(xiàn)這個(gè)Blob URL的請(qǐng)求信息

Blob URL和Data URL的區(qū)別

還可以使用Data URL方式加載圖片資源:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Blob Test</title>
    <script>
        function handleFile(e) {
            var file = e.files[0];
            var fileReader = new FileReader();
            var img = document.getElementsByTagName("img")[0];
            fileReader.onload = function(e) {
                img.src = e.target.result;
            }
            fileReader.readAsDataURL(file);
        }
    </script>
</head>

<body>
    <input type="file" accept="image/*" onchange="handleFile(this)" />
    <br/>
    <img style="width:200px;height:200px">
</body>

</html>

FileReader的readAsDataURL生成一個(gè)Data URL,如圖所示:


image

web性能優(yōu)化中有一項(xiàng)措施惭蹂,把小圖片用base64編碼直接遷入到HTML文件中伞插,實(shí)際上就是利用了Data URL來(lái)獲取嵌入的圖片數(shù)據(jù)。

Blob URL和Data URL的區(qū)別

  • Blob URL的長(zhǎng)度一般比較短盾碗,但Data URL因?yàn)橹苯哟鎯?chǔ)圖片base64編碼后的數(shù)據(jù)媚污,往往很長(zhǎng),如上圖所示廷雅,瀏覽器在顯示Data URL時(shí)使用了省略號(hào)(…)耗美。當(dāng)顯式大圖片時(shí),使用Blob URL能獲取更好的可能性
  • Blob URL可以方便的使用XMLHttpRequest獲取源數(shù)據(jù)
var blobUrl = URL.createObjectURL(new Blob(['Test'], {type: 'text/plain'}));
var x = new XMLHttpRequest();
// 如果設(shè)置x.responseType = 'blob'航缀,將返回一個(gè)Blob對(duì)象商架,而不是文本:
// x.responseType = 'blob';
x.onload = function() {
    alert(x.responseText);   // 輸出 Test
};
x.open('get', blobUrl);
x.send();
  • Blob URL只能在當(dāng)前應(yīng)用內(nèi)部使用,把Blob URL復(fù)制到瀏覽器的地址中芥玉,是無(wú)法獲取數(shù)據(jù)的(外部無(wú)法獲壬呙)。而Data URL可以在瀏覽器中使用灿巧,具有較好的移植性

指定文件類型

除了可以用作圖片資源的網(wǎng)絡(luò)地址皇型,Blob URL也可以用作其他資源的網(wǎng)絡(luò)地址,例如html文件砸烦、json文件等弃鸦,為了保證瀏覽器能正確的解析Blob URL返回的文件類型,需要在創(chuàng)建Blob對(duì)象時(shí)指定相應(yīng)的type

// 創(chuàng)建HTML文件的Blob URL
var data = "<div style='color:red;'>This is a blob</div>";
var blob = new Blob([data], { type: 'text/html' });
var blobURL = URL.createObjectURL(blob);

// 創(chuàng)建JSON文件的Blob URL
var data = { "name": "abc" };
var blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
var blobURL = URL.createObjectURL(blob);

Blob和ArrayBuffer

ArrayBuffer對(duì)象用來(lái)表示通用的幢痘、固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)唬格。
通過(guò)new ArrayBuffer(length)來(lái)獲得一片連續(xù)的內(nèi)存空間,它不能直接讀寫,但可根據(jù)需要將其傳遞到TypedArray視圖或者DataView對(duì)象來(lái)解釋原始緩沖區(qū)购岗。
實(shí)際上視圖只是給我們提供了一個(gè)某種類型的讀寫接口汰聋,讓我們可以操作ArrayBuffer里的數(shù)據(jù)。
TypedArray需要制定一個(gè)數(shù)組類型來(lái)保證數(shù)組成員都是一個(gè)數(shù)據(jù)類型喊积,而DataView數(shù)組成員可以是不同的數(shù)據(jù)類型烹困。

TypedArray視圖的類型數(shù)組對(duì)象:(他們的構(gòu)造函數(shù)都接收一個(gè)ArrayBuffer參數(shù)進(jìn)行轉(zhuǎn)換,由于ArrayBuffer不能直接讀惹恰)

  • Int8Array:8位有符號(hào)整數(shù)髓梅,長(zhǎng)度1個(gè)字節(jié)。
  • Uint8Array:8位無(wú)符號(hào)整數(shù)绎签,長(zhǎng)度1個(gè)字節(jié)枯饿。
  • Uint8ClampedArray:8位無(wú)符號(hào)整數(shù),長(zhǎng)度1個(gè)字節(jié)诡必,溢出處理不同奢方。
  • Int16Array:16位有符號(hào)整數(shù),長(zhǎng)度2個(gè)字節(jié)爸舒。
  • Uint16Array:16位無(wú)符號(hào)整數(shù)蟋字,長(zhǎng)度2個(gè)字節(jié)牍蜂。
  • Int32Array:32位有符號(hào)整數(shù)吏饿,長(zhǎng)度4個(gè)字節(jié)磁玉。
  • Uint32Array:32位無(wú)符號(hào)整數(shù)榛瓮,長(zhǎng)度4個(gè)字節(jié)。
  • Float32Array:32位浮點(diǎn)數(shù)远寸,長(zhǎng)度4個(gè)字節(jié)。
  • Float64Array:64位浮點(diǎn)數(shù),長(zhǎng)度8個(gè)字節(jié)璧尸。

Blob與ArrayBuffer的區(qū)別是,除了原始字節(jié)以外它還提供了Mime type作為原數(shù)據(jù)熬拒,Blob和ArrayBuffer之間可以進(jìn)行轉(zhuǎn)換爷光,F(xiàn)ile對(duì)象其實(shí)繼承自Blob對(duì)象,并提供了name澎粟、lastModifiedDate蛀序、size、type等基礎(chǔ)元數(shù)據(jù)

Blob對(duì)象轉(zhuǎn)換成ArrayBuffer

//創(chuàng)建一個(gè)以二進(jìn)制數(shù)據(jù)存儲(chǔ)的html文件
const text = "<div>hello world</div>"
const blob = new Blob([text],{type:"text/html"})
//以文本讀取
const textReader = new FileReader()
textReader.readAsText(blob)
textReader.onload = function(){
    console.log(textReader.result);//<div> hello word</div>
}
//以ArrayBuffer讀取
const bufReader = new FileReader()
bufReader.readAsArrayBuffer(blob)
bufReader.onload = function(){
    console.log(new Uint8Array(bufReader.result)) // Uint8Array(22) [60, 100, 105, 118, 62, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 60, 47, 100, 105, 118, 62]
}

ArrayBuffer轉(zhuǎn)換成Blob

const u8Buf = new Uint8Array([60, 100, 105, 118, 62, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 60, 47, 100, 105, 118, 62]);
const u8Blob = new Blob([u8Buf], { type: "text/html" }); // Blob {size: 22, type: "text/html"}
const textReader = new FileReader();

textReader.readAsText(u8Blob);
textReader.onload = function() {
  console.log(textReader.result); // 同樣得到div>hello world</div>
};

從后臺(tái)獲取Blob(File)

通過(guò)正確的設(shè)置responseType我們可以直接獲取到Blob對(duì)象

function ajax(url,cb){
    const xhr = new XMLHttpRequest()
    xhr.open("get",url)
    //"text"-字符串 "blob"-Blob對(duì)象 "arraybuffer"-ArrayBuffer對(duì)象
    xhr.responseType = "blob"
    xhr.onload = function(){
        cb(xhr.response)
    }
    xhr.send
}

通過(guò)請(qǐng)求一個(gè)Blob對(duì)象或者ArrayBuffer再轉(zhuǎn)換成Blob對(duì)象活烙,再通過(guò)URL.createObjectURL生成BlobURL賦值給src屬性即可

ajax('video.mp4', function(res){
    const src = URL.createObjectURL(res); 
    video.src = src;
})

MediaSource(流媒體播放徐裸,視頻流)

video標(biāo)簽src指向一個(gè)視頻地址,視頻播完了再將src修改為下一段的視頻地址然后播放啸盏,這顯然不符合我們無(wú)縫播放的要求重贺。其實(shí)有了我們前面Blob URL的學(xué)習(xí),我們可能就會(huì)想到一個(gè)思路,用Blob URL指向一個(gè)視頻二進(jìn)制數(shù)據(jù)气笙,然后不斷將下一段視頻的二進(jìn)制數(shù)據(jù)添加拼接進(jìn)去次企。這樣就可以在不影響播放的情況下,不斷的更新視頻內(nèi)容并播放下去潜圃,想想是不是有點(diǎn)流的意思出來(lái)了缸棵。

要實(shí)現(xiàn)這個(gè)功能我們要通過(guò)MediaSource來(lái)實(shí)現(xiàn),MediaSource接口功能也很純粹谭期,作為一個(gè)媒體數(shù)據(jù)容器可以和HTMLMediaElement進(jìn)行綁定堵第。基本流程就是通過(guò)URL.createObjectURL創(chuàng)建容器的BLob URL崇堵,設(shè)置到video標(biāo)簽的src上型诚,在播放過(guò)程中,我們?nèi)匀豢梢酝ㄟ^(guò)MediaSource.appendBuffer方法往容器里添加數(shù)據(jù)鸳劳,達(dá)到更新視頻內(nèi)容的目的狰贯。

可以理解MediaSource為一個(gè)Blob的容器,可以通過(guò)addSourceBuffer來(lái)創(chuàng)建一個(gè)指定類型的Blob容器赏廓,這個(gè)容器可以通過(guò)appendBuffer不斷的往里面添加數(shù)據(jù)

const video = document.querySelector('video');
//視頻資源存放路徑涵紊,假設(shè)下面有5個(gè)分段視頻 video1.mp4 ~ video5.mp4,第一個(gè)段為初始化視頻init.mp4
const assetURL = "http://www.demo.com";
//視頻格式和編碼信息幔摸,主要為判斷瀏覽器是否支持視頻格式摸柄,但如果信息和視頻不符可能會(huì)報(bào)錯(cuò)
const mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'; 
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
  const mediaSource = new MediaSource();
  video.src = URL.createObjectURL(mediaSource); //將video與MediaSource綁定,此處生成一個(gè)Blob URL
  mediaSource.addEventListener('sourceopen', sourceOpen); //可以理解為容器打開
} else {
  //瀏覽器不支持該視頻格式
  console.error('Unsupported MIME type or codec: ', mimeCodec);
}

function sourceOpen () {
  const mediaSource = this;
  const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
  let i = 1;
  function getNextVideo(url) {
    //ajax代碼實(shí)現(xiàn)翻看上文既忆,數(shù)據(jù)請(qǐng)求類型為arraybuffer
    ajax(url, function(buf) {
      //往容器中添加請(qǐng)求到的數(shù)據(jù)驱负,不會(huì)影響當(dāng)下的視頻播放。
      sourceBuffer.appendBuffer(buf);
    });
  }
  //每次appendBuffer數(shù)據(jù)更新完之后就會(huì)觸發(fā)
  sourceBuffer.addEventListener("updateend", function() {
    if (i === 1) {
      //第一個(gè)初始化視頻加載完就開始播放
      video.play();
    }
    if (i < 6) {
      //一段視頻加載完成后患雇,請(qǐng)求下一段視頻
      getNextVideo(`${assetURL}/video${i}.mp4`);
    }
    if (i === 6) {
      //全部視頻片段加載完關(guān)閉容器
      mediaSource.endOfStream();
      URL.revokeObjectURL(video.src); //Blob URL已經(jīng)使用并加載跃脊,不需要再次使用的話可以釋放掉。
    }
    i++;
  });
  //加載初始視頻
  getNextVideo(`${assetURL}/init.mp4`);
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末苛吱,一起剝皮案震驚了整個(gè)濱河市酪术,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翠储,老刑警劉巖绘雁,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異援所,居然都是意外死亡庐舟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門住拭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)继阻,“玉大人耻涛,你說(shuō)我怎么就攤上這事∥灵荩” “怎么了抹缕?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)墨辛。 經(jīng)常有香客問(wèn)我卓研,道長(zhǎng),這世上最難降的妖魔是什么睹簇? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任奏赘,我火速辦了婚禮,結(jié)果婚禮上太惠,老公的妹妹穿的比我還像新娘磨淌。我一直安慰自己,他們只是感情好凿渊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布梁只。 她就那樣靜靜地躺著,像睡著了一般埃脏。 火紅的嫁衣襯著肌膚如雪搪锣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天彩掐,我揣著相機(jī)與錄音构舟,去河邊找鬼。 笑死堵幽,一個(gè)胖子當(dāng)著我的面吹牛狗超,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播朴下,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼努咐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了桐猬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤刽肠,失蹤者是張志新(化名)和其女友劉穎溃肪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體音五,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惫撰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了躺涝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厨钻。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出夯膀,到底是詐尸還是另有隱情诗充,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布诱建,位于F島的核電站蝴蜓,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏俺猿。R本人自食惡果不足惜茎匠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望押袍。 院中可真熱鬧诵冒,春花似錦、人聲如沸谊惭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)午笛。三九已至惭蟋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間药磺,已是汗流浹背告组。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留癌佩,地道東北人木缝。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像围辙,于是被迫代替她去往敵國(guó)和親我碟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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