JavaWeb實(shí)現(xiàn)文件上傳、下載功能

前言

在Web應(yīng)用系統(tǒng)開(kāi)發(fā)中汰翠,文件上傳和下載功能是非常常用的功能,今天來(lái)講一下JavaWeb中的文件上傳和下載功能的實(shí)現(xiàn)昭雌。

對(duì)于文件上傳复唤,瀏覽器在上傳的過(guò)程中是將文件以流的形式提交到服務(wù)器端的,如果直接使用Servlet獲取上傳文件的輸入流然后再解析里面的請(qǐng)求參數(shù)是比較麻煩烛卧,所以一般選擇采用apache的開(kāi)源工具common-fileupload這個(gè)文件上傳組件佛纫。這個(gè)common-fileupload上傳組件的jar包可以去apache官網(wǎng)上面下載,也可以在struts的lib文件夾下面找到总放,struts上傳的功能就是基于這個(gè)實(shí)現(xiàn)的呈宇。common-fileupload是依賴(lài)于common-io這個(gè)包的,所以還需要下載這個(gè)包局雄。

一甥啄、開(kāi)發(fā)環(huán)境搭建

創(chuàng)建一個(gè)FileUploadAndDownLoad項(xiàng)目,加入Apache的commons-fileupload文件上傳組件的相關(guān)Jar包哎榴,如下圖所示:

項(xiàng)目路徑
二型豁、實(shí)現(xiàn)文件上傳
2.1、文件上傳頁(yè)面和消息提示頁(yè)面

upload.jsp頁(yè)面的代碼如下:
<pre>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>文件上傳</title>
</head>

<body>
<form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post">
上傳用戶:<input type="text" name="username">

上傳文件1:<input type="file" name="file1">

上傳文件2:<input type="file" name="file2">

<input type="submit" value="提交">
</form>
</body>
</html>
</pre>

message.jsp的代碼如下:
<pre>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>消息提示</title>
</head>

<body>
${message}
</body>
</html>
</pre>

2.2尚蝌、處理文件上傳的Servlet

文件上傳功能有許多需要注意的小細(xì)節(jié)問(wèn)題迎变,以下列出的幾點(diǎn)需要特別注意:

1、為保證服務(wù)器安全飘言,上傳文件應(yīng)該放在外界無(wú)法直接訪問(wèn)的目錄下衣形,比如放于WEB-INF目錄下。
  2、為防止文件覆蓋的現(xiàn)象發(fā)生谆吴,要為上傳文件產(chǎn)生一個(gè)唯一的文件名倒源。
  3、為防止一個(gè)目錄下面出現(xiàn)太多文件句狼,要使用hash算法打散存儲(chǔ)笋熬。
  4、要限制上傳文件的最大值腻菇。
  5胳螟、要限制上傳文件的類(lèi)型,在收到上傳文件名時(shí)筹吐,判斷后綴名是否合法糖耸。

UploadHandleServlet的代碼如下:
<pre>
package me.gacl.web.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**

  • @ClassName: UploadHandleServlet
  • @Description: TODO(這里用一句話描述這個(gè)類(lèi)的作用)
  • @author: 孤傲蒼狼
  • @date: 2015-1-3 下午11:35:50

*/
public class UploadHandleServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到上傳文件的保存目錄,將上傳的文件存放于WEB-INF目錄下丘薛,不允許外界直接訪問(wèn)嘉竟,保證上傳文件的安全
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//上傳時(shí)生成的臨時(shí)文件保存目錄
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tmpFile = new File(tempPath);
if (!tmpFile.exists()) {
//創(chuàng)建臨時(shí)目錄
tmpFile.mkdir();
}

 //消息提示
 String message = "";
 try{
  //使用Apache文件上傳組件處理文件上傳步驟:
  //1、創(chuàng)建一個(gè)DiskFileItemFactory工廠
  DiskFileItemFactory factory = new DiskFileItemFactory();
  //設(shè)置工廠的緩沖區(qū)的大小洋侨,當(dāng)上傳的文件大小超過(guò)緩沖區(qū)的大小時(shí)舍扰,就會(huì)生成一個(gè)臨時(shí)文件存放到指定的臨時(shí)目錄當(dāng)中。
  factory.setSizeThreshold(1024*100);//設(shè)置緩沖區(qū)的大小為100KB凰兑,如果不指定妥粟,那么緩沖區(qū)的大小默認(rèn)是10KB
  //設(shè)置上傳時(shí)生成的臨時(shí)文件的保存目錄
  factory.setRepository(tmpFile);
  //2、創(chuàng)建一個(gè)文件上傳解析器
  ServletFileUpload upload = new ServletFileUpload(factory);
  //監(jiān)聽(tīng)文件上傳進(jìn)度
  upload.setProgressListener(new ProgressListener(){
   public void update(long pBytesRead, long pContentLength, int arg2) {
    System.out.println("文件大小為:" + pContentLength + ",當(dāng)前已處理:" + pBytesRead);
    /**
    * 文件大小為:14608,當(dāng)前已處理:4096
     文件大小為:14608,當(dāng)前已處理:7367
     文件大小為:14608,當(dāng)前已處理:11419
     文件大小為:14608,當(dāng)前已處理:14608
    */
   }
  });
  //解決上傳文件名的中文亂碼
  upload.setHeaderEncoding("UTF-8"); 
  //3吏够、判斷提交上來(lái)的數(shù)據(jù)是否是上傳表單的數(shù)據(jù)
  if(!ServletFileUpload.isMultipartContent(request)){
   //按照傳統(tǒng)方式獲取數(shù)據(jù)
   return;
  }
   
  //設(shè)置上傳單個(gè)文件的大小的最大值勾给,目前是設(shè)置為1024*1024字節(jié),也就是1MB
  upload.setFileSizeMax(1024*1024);
  //設(shè)置上傳文件總量的最大值锅知,最大值=同時(shí)上傳的多個(gè)文件的大小的最大值的和播急,目前設(shè)置為10MB
  upload.setSizeMax(1024*1024*10);
  //4、使用ServletFileUpload解析器解析上傳數(shù)據(jù)售睹,解析結(jié)果返回的是一個(gè)List<FileItem>集合桩警,每一個(gè)FileItem對(duì)應(yīng)一個(gè)Form表單的輸入項(xiàng)
  List<FileItem> list = upload.parseRequest(request);
  for(FileItem item : list){
   //如果fileitem中封裝的是普通輸入項(xiàng)的數(shù)據(jù)
   if(item.isFormField()){
    String name = item.getFieldName();
    //解決普通輸入項(xiàng)的數(shù)據(jù)的中文亂碼問(wèn)題
    String value = item.getString("UTF-8");
    //value = new String(value.getBytes("iso8859-1"),"UTF-8");
    System.out.println(name + "=" + value);
   }else{//如果fileitem中封裝的是上傳文件
    //得到上傳的文件名稱(chēng),
    String filename = item.getName();
    System.out.println(filename);
    if(filename==null || filename.trim().equals("")){
     continue;
    }
    //注意:不同的瀏覽器提交的文件名是不一樣的昌妹,有些瀏覽器提交上來(lái)的文件名是帶有路徑的捶枢,如: c:\a\b\1.txt,而有些只是單純的文件名飞崖,如:1.txt
    //處理獲取到的上傳文件的文件名的路徑部分烂叔,只保留文件名部分
    filename = filename.substring(filename.lastIndexOf("\\")+1);
    //得到上傳文件的擴(kuò)展名
    String fileExtName = filename.substring(filename.lastIndexOf(".")+1);
    //如果需要限制上傳的文件類(lèi)型,那么可以通過(guò)文件的擴(kuò)展名來(lái)判斷上傳的文件類(lèi)型是否合法
    System.out.println("上傳的文件的擴(kuò)展名是:"+fileExtName);
    //獲取item中的上傳文件的輸入流
    InputStream in = item.getInputStream();
    //得到文件保存的名稱(chēng)
    String saveFilename = makeFileName(filename);
    //得到文件的保存目錄
    String realSavePath = makePath(saveFilename, savePath);
    //創(chuàng)建一個(gè)文件輸出流
    FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);
   //創(chuàng)建一個(gè)緩沖區(qū)
    byte buffer[] = new byte[1024];
    //判斷輸入流中的數(shù)據(jù)是否已經(jīng)讀完的標(biāo)識(shí)        int len = 0;
    //循環(huán)將輸入流讀入到緩沖區(qū)當(dāng)中固歪,(len=in.read(buffer))>0就表示in里面還有數(shù)據(jù)
    while((len=in.read(buffer))>0){
     //使用FileOutputStream輸出流將緩沖區(qū)的數(shù)據(jù)寫(xiě)入到指定的目錄(savePath + "\\" + filename)當(dāng)中
     out.write(buffer, 0, len);
    }
    //關(guān)閉輸入流
    in.close();
    //關(guān)閉輸出流
    out.close();        //刪除處理文件上傳時(shí)生成的臨時(shí)文件        //item.delete();        message = "文件上傳成功蒜鸡!";
   }
  }
 }catch (FileUploadBase.FileSizeLimitExceededException e) {
  e.printStackTrace();
  request.setAttribute("message", "單個(gè)文件超出最大值!!逢防!");
  request.getRequestDispatcher("/message.jsp").forward(request, response);
  return;
 }catch (FileUploadBase.SizeLimitExceededException e) {
  e.printStackTrace();
  request.setAttribute("message", "上傳文件的總的大小超出限制的最大值R杜妗!忘朝!");
  request.getRequestDispatcher("/message.jsp").forward(request, response);
  return;
 }catch (Exception e) {
  message= "文件上傳失敾沂稹!";
  e.printStackTrace();
 }
 request.setAttribute("message",message);
 request.getRequestDispatcher("/message.jsp").forward(request, response);

}

/**

  • @Method: makeFileName
  • @Description: 生成上傳文件的文件名辜伟,文件名以:uuid+"_"+文件的原始名稱(chēng)
  • @Anthor:孤傲蒼狼
  • @param filename 文件的原始名稱(chēng)
  • @return uuid+""+文件的原始名稱(chēng)
    */
    private String makeFileName(String filename){ //2.jpg
    //為防止文件覆蓋的現(xiàn)象發(fā)生氓侧,要為上傳文件產(chǎn)生一個(gè)唯一的文件名
    return UUID.randomUUID().toString() + "
    " + filename;
    }
    /**
  • 為防止一個(gè)目錄下面出現(xiàn)太多文件,要使用hash算法打散存儲(chǔ)
  • @Method: makePath
  • @Description:
  • @Anthor:孤傲蒼狼
  • @param filename 文件名导狡,要根據(jù)文件名生成存儲(chǔ)目錄
  • @param savePath 文件存儲(chǔ)路徑
  • @return 新的存儲(chǔ)目錄
    */
    private String makePath(String filename,String savePath){
    //得到文件名的hashCode的值,得到的就是filename這個(gè)字符串對(duì)象在內(nèi)存中的地址
    int hashcode = filename.hashCode();
    int dir1 = hashcode&0xf; //0--15
    int dir2 = (hashcode&0xf0)>>4; //0-15
    //構(gòu)造新的保存目錄
    String dir = savePath + "\" + dir1 + "\" + dir2; //upload\2\3 upload\3\5
    //File既可以代表文件也可以代表目錄 File file = new File(dir);
    //如果目錄不存在
    if(!file.exists()){
    //創(chuàng)建目錄
    file.mkdirs();
    }
    return dir;
    }

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

doGet(request, response);
}
}
</pre>

在Web.xml文件中注冊(cè)UploadHandleServlet
<pre>
<servlet>
<servlet-name>UploadHandleServlet</servlet-name>
<servlet-class>me.gacl.web.controller.UploadHandleServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>UploadHandleServlet</servlet-name>
<url-pattern>/servlet/UploadHandleServlet</url-pattern>
</servlet-mapping>
</pre>

以上就可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的文件上傳功能了偎痛。

=============== 這只是分割線 ===================
三旱捧、實(shí)現(xiàn)文件下載
3.1、列出提供下載的文件資源

我們要將Web應(yīng)用系統(tǒng)中的文件資源提供給用戶進(jìn)行下載踩麦,首先我們要有一個(gè)頁(yè)面列出上傳文件目錄下的所有文件枚赡,當(dāng)用戶點(diǎn)擊文件下載超鏈接時(shí)就進(jìn)行下載操作,編寫(xiě)一個(gè)ListFileServlet谓谦,用于列出Web應(yīng)用系統(tǒng)中所有下載文件贫橙。

ListFileServlet的代碼如下:
<pre>
package me.gacl.web.controller;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**

  • @ClassName: ListFileServlet
  • @Description: 列出Web系統(tǒng)中所有下載文件
  • @author: 孤傲蒼狼
  • @date: 2015-1-4 下午9:54:40

*/
public class ListFileServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取上傳文件的目錄
String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//存儲(chǔ)要下載的文件名
Map<String,String> fileNameMap = new HashMap<String,String>();
//遞歸遍歷filepath目錄下的所有文件和目錄,將文件的文件名存儲(chǔ)到map集合中
listfile(new File(uploadFilePath),fileNameMap);//File既可以代表一個(gè)文件也可以代表一個(gè)目錄
//將Map集合發(fā)送到listfile.jsp頁(yè)面進(jìn)行顯示
request.setAttribute("fileNameMap", fileNameMap);
request.getRequestDispatcher("/listfile.jsp").forward(request, response);
}

/**

  • @Method: listfile
  • @Description: 遞歸遍歷指定目錄下的所有文件
  • @Anthor:孤傲蒼狼
  • @param file 即代表一個(gè)文件反粥,也代表一個(gè)文件目錄
  • @param map 存儲(chǔ)文件名的Map集合
    /
    public void listfile(File file,Map<String,String> map){
    //如果file代表的不是一個(gè)文件卢肃,而是一個(gè)目錄
    if(!file.isFile()){
    //列出該目錄下的所有文件和目錄
    File files[] = file.listFiles();
    //遍歷files[]數(shù)組
    for(File f : files){
    //遞歸
    listfile(f,map);
    }
    }else{
    /
    *
  • 處理文件名,上傳后的文件是以u(píng)uid_文件名的形式去重新命名的才顿,去除文件名的uuid_部分
    file.getName().indexOf("")檢索字符串中第一次出現(xiàn)""字符的位置莫湘,如果文件名類(lèi)似于:9349249849-88343-8344_阿達(dá).avi
    那么file.getName().substring(file.getName().indexOf("")+1)處理之后就可以得到阿達(dá).avi部分
    */
    String realName = file.getName().substring(file.getName().indexOf("
    ")+1);
    //file.getName()得到的是文件的原始名稱(chēng),這個(gè)名稱(chēng)是唯一的郑气,因此可以作為key,realName是處理過(guò)后的名稱(chēng),有可能會(huì)重復(fù)
    map.put(file.getName(), realName);
    }
    }

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
</pre>

這里簡(jiǎn)單說(shuō)一下ListFileServlet中l(wèi)istfile方法弦讽,listfile方法是用來(lái)列出目錄下的所有文件的磕道,listfile方法內(nèi)部用到了遞歸,在實(shí)際開(kāi)發(fā)當(dāng)中讳侨,我們肯定會(huì)在數(shù)據(jù)庫(kù)創(chuàng)建一張表呵萨,里面會(huì)存儲(chǔ)上傳的文件名以及文件的具體存放目錄,我們通過(guò)查詢(xún)表就可以知道文件的具體存放目錄爷耀,是不需要用到遞歸操作的甘桑,這個(gè)例子是因?yàn)闆](méi)有使用數(shù)據(jù)庫(kù)存儲(chǔ)上傳的文件名和文件的具體存放位置,而上傳文件的存放位置又使用了散列算法打散存放,所以需要用到遞歸跑杭,在遞歸時(shí)铆帽,將獲取到的文件名存放到從外面?zhèn)鬟f到listfile方法里面的Map集合當(dāng)中,這樣就可以保證所有的文件都存放在同一個(gè)Map集合當(dāng)中德谅。

在Web.xml文件中配置ListFileServlet

<pre>
<servlet>
<servlet-name>ListFileServlet</servlet-name>
<servlet-class>me.gacl.web.controller.ListFileServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ListFileServlet</servlet-name>
<url-pattern>/servlet/ListFileServlet</url-pattern>
</servlet-mapping>
</pre>

展示下載文件的listfile.jsp頁(yè)面如下
<pre>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML>
<html>
<head>
<title>下載文件顯示頁(yè)面</title>
</head>

<body>

<c:forEach var="me" items="${fileNameMap}">
<c:url value="/servlet/DownLoadServlet" var="downurl">
<c:param name="filename" value="${me.key}"></c:param>
</c:url>
${me.value}<a href="${downurl}">下載</a>


</c:forEach>
</body>
</html>
</pre>

訪問(wèn)ListFileServlet爹橱,就可以在listfile.jsp頁(yè)面中顯示提供給用戶下載的文件資源,如下圖所示:

下載列表
3.2窄做、實(shí)現(xiàn)文件下載

編寫(xiě)一個(gè)用于處理文件下載的Servlet愧驱,DownLoadServlet的代碼如下:

<pre>
package me.gacl.web.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DownLoadServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到要下載的文件名
String fileName = request.getParameter("filename"); //23239283-92489-阿凡達(dá).avi
fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
//上傳的文件都是保存在/WEB-INF/upload目錄下的子目錄當(dāng)中
String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");
//通過(guò)文件名找出文件的所在目錄
String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
//得到要下載的文件
File file = new File(path + "\" + fileName);
//如果文件不存在
if(!file.exists()){
request.setAttribute("message", "您要下載的資源已被刪除!椭盏!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//處理文件名
String realname = fileName.substring(fileName.indexOf("_")+1);
//設(shè)置響應(yīng)頭组砚,控制瀏覽器下載該文件
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
//讀取要下載的文件,保存到文件輸入流
FileInputStream in = new FileInputStream(path + "\" + fileName);
//創(chuàng)建輸出流
OutputStream out = response.getOutputStream();
//創(chuàng)建緩沖區(qū)
byte buffer[] = new byte[1024];
int len = 0;
//循環(huán)將輸入流中的內(nèi)容讀取到緩沖區(qū)當(dāng)中
while((len=in.read(buffer))>0){
//輸出緩沖區(qū)的內(nèi)容到瀏覽器掏颊,實(shí)現(xiàn)文件下載
out.write(buffer, 0, len);
}
//關(guān)閉文件輸入流
in.close();
//關(guān)閉輸出流
out.close();
}

/**

  • @Method: findFileSavePathByFileName
  • @Description: 通過(guò)文件名和存儲(chǔ)上傳文件根目錄找出要下載的文件的所在路徑
  • @Anthor:孤傲蒼狼
  • @param filename 要下載的文件名
  • @param saveRootPath 上傳文件保存的根目錄糟红,也就是/WEB-INF/upload目錄
  • @return 要下載的文件的存儲(chǔ)目錄
    */
    public String findFileSavePathByFileName(String filename,String saveRootPath){
    int hashcode = filename.hashCode();
    int dir1 = hashcode&0xf; //0--15
    int dir2 = (hashcode&0xf0)>>4; //0-15
    String dir = saveRootPath + "\" + dir1 + "\" + dir2; //upload\2\3 upload\3\5
    File file = new File(dir);
    if(!file.exists()){
    //創(chuàng)建目錄
    file.mkdirs();
    }
    return dir;
    }

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
</pre>

在Web.xml文件中配置DownLoadServlet

<pre>
<servlet>
<servlet-name>DownLoadServlet</servlet-name>
<servlet-class>me.gacl.web.controller.DownLoadServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>DownLoadServlet</servlet-name>
<url-pattern>/servlet/DownLoadServlet</url-pattern>
</servlet-mapping>
</pre>

點(diǎn)擊【下載】超鏈接,將請(qǐng)求提交到DownLoadServlet就行處理就可以實(shí)現(xiàn)文件下載了,文件下載的操作到這里就可以簡(jiǎn)單實(shí)現(xiàn)了乌叶。

最后編輯于
?著作權(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)店門(mén)谈撒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人匾南,你說(shuō)我怎么就攤上這事啃匿。” “怎么了蛆楞?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵溯乒,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我豹爹,道長(zhǎng)裆悄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任臂聋,我火速辦了婚禮光稼,結(jié)果婚禮上或南,老公的妹妹穿的比我還像新娘。我一直安慰自己艾君,他們只是感情好采够,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著冰垄,像睡著了一般蹬癌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虹茶,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天逝薪,我揣著相機(jī)與錄音,去河邊找鬼蝴罪。 笑死董济,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洲炊。 我是一名探鬼主播感局,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼暂衡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起崖瞭,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤狂巢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后书聚,有當(dāng)?shù)厝嗽跇?shù)林里發(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
  • 文/蒙蒙 一嘁圈、第九天 我趴在偏房一處隱蔽的房頂上張望省骂。 院中可真熱鬧,春花似錦最住、人聲如沸钞澳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)略贮。三九已至,卻和暖如春仗岖,著一層夾襖步出監(jiān)牢的瞬間逃延,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工轧拄, 沒(méi)想到剛下飛機(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)容