精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

在ASP.NET MVC中實現大文件異步上傳

原創
開發 后端
在ASP.NET MVC中,我們使用StaticWorkerRequest建立虛假聲明的方式實現大文件上傳,現在你可以在ASP.NET MVC中通過直接訪問數據流上傳大文件,同時還可保證內存資源的消耗相對平穩。

【51CTO獨家特稿】在ASP.NET中通過HTTP上傳大文件是一個由來已久的挑戰,它是許多活躍的ASP.NET論壇最常討論的問題之一,除了處理大文件外,用戶還經常被要求要顯示出文件上傳的進度,當你需要直接控制從瀏覽器上傳數據流時,你會四處碰壁。51CTO.com之前就曾針對性的報道過《解除ASP.NET上傳文件的大小限制》和《ASP.NET大文件上傳開發總結》等文章。

絕大多數人認為在ASP.NET中上傳大文件有以下這些解決方案:

◆不要這樣做。你***是在頁面中嵌入一個Silverlight或Flash進程上傳文件。

◆不要這樣做。因為HTTP本身設計就不是為了上傳大文件,重新思考你要的功能。

◆不要這樣做。ASP.NET本身設計***也就能處理2GB大小的文件。

◆購買商業產品,如SlickUpload,它使用了一個HttpModule實現了文件流分塊。

◆使用開源產品,如NeatUpload,它使用了一個HttpModule實現了文件流分塊。

最近我接到一個任務,需構建一個上傳工具實現以下功能:

◆必須工作在HTTP協議

◆必須允許非常大的文件上傳(會大于2GB)

◆必須允許斷點續傳

◆必須允許并行上傳

因此前三個解決方案都不適應我的需求,其它解決方案對于我而言又太笨重了,因此我開始著手解決在ASP.NET MVC中的這個問題,如果有這方面的開發背景,你一定了解大部分問題最終都歸結于對ASP.NET輸入流和連鎖請求過程的控制,網上的資料一般都是這樣描述的,只要你的代碼訪問了HttpRequest的InputStream屬性,在你訪問流之前,ASP.NET就會緩存整個上傳的文件,這就意味著當我向云服務上傳文件時,我必須等待整個大文件抵達服務器,然后才能將其傳輸到預定目的地,這意味著需要兩倍的時間。

首先,我們推薦你閱讀一下Scott Hanselman的有關ASP.NET MVC文件上傳文章,地址http://www.hanselman.com/blog/CommentView.aspx?guid=bc137b6b-d8d0-47d1-9795-f8814f7d1903,先對文件上傳有一個大致的了解,但Scott Hanselman的方法是不能上傳大文件的,根據Scott Hanselman的方法,你只需要修改一下web.config文件,確保ASP.NET允許***支持2GB大小的文件上傳,不要擔心,這樣設置并不會吃掉你的內存,因為凡是大于256KB的數據都被緩存到磁盤上去了。

  1. ﹤system.web﹥  
  2. ﹤httpruntime requestlengthdiskthreshold="256" maxrequestlength="2097151"﹥  
  3. ﹤/httpruntime﹥﹤/system.web﹥ 

這是一個簡單的適合大多數應用的解決辦法,但我的任務中不能借用這種方法,即使會將數據緩存到磁盤中,但這種類似于另存為的方法也會使用大量的內存。

通過緩存整個文件的方式,內存消耗突然上升 
圖 1 :通過緩存整個文件,然后另存為的方式會使內存消耗突然上升

那么在ASP.NET MVC中通過直接訪問流,不觸發任何緩存機制,上傳大文件該如何實現呢?解決辦法就是盡量遠離ASP.NET,我們先來看一看UploadController,它有三個行為方法,一個是索引我們上傳的文件,一個是前面討論的緩存邏輯,另一個是基于實時流的方法。

  1. public class UploadController : Controller  
  2. {  
  3.     [AcceptVerbs(HttpVerbs.Get)]  
  4.     [Authorize]  
  5.     public ActionResult Index()  
  6.     {  
  7.         return View();  
  8.     }  
  9.  
  10.     [AcceptVerbs(HttpVerbs.Post)]  
  11.     public ActionResult BufferToDisk()  
  12.     {  
  13.         var path = Server.MapPath("~/Uploads");  
  14.  
  15.         foreach (string file in Request.Files)  
  16.         {  
  17.             var fileBase = Request.Files[file];  
  18.  
  19.             try 
  20.             {  
  21.                 if (fileBase.ContentLength > 0)  
  22.                 {  
  23.                     fileBase.SaveAs(Path.Combine(path, fileBase.FileName));  
  24.                 }  
  25.             }  
  26.             catch (IOException)  
  27.             {  
  28.  
  29.             }  
  30.         }  
  31.  
  32.         return RedirectToAction("Index""Upload");  
  33.     }  
  34.  
  35.     //[AcceptVerbs(HttpVerbs.Post)]  
  36.     //[Authorize]  
  37.     public void LiveStream()  
  38.     {  
  39.         var path = Server.MapPath("~/Uploads");  
  40.  
  41.         var context = ControllerContext.HttpContext;  
  42.  
  43.         var provider = (IServiceProvider)context;  
  44.  
  45.         var workerRequest = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));  
  46.  
  47.         //[AcceptVerbs(HttpVerbs.Post)]  
  48.         var verb = workerRequest.GetHttpVerbName();  
  49.         if(!verb.Equals("POST"))  
  50.         {  
  51.             Response.StatusCode = (int)HttpStatusCode.NotFound;  
  52.             Response.SuppressContent = true;  
  53.             return;  
  54.         }  
  55.  
  56.         //[Authorize]  
  57.         if(!context.User.Identity.IsAuthenticated)  
  58.         {  
  59.             Response.StatusCode = (int)HttpStatusCode.Unauthorized;  
  60.             Response.SuppressContent = true;  
  61.             return;  
  62.         }  
  63.  
  64.         var encoding = context.Request.ContentEncoding;  
  65.  
  66.         var processor = new UploadProcessor(workerRequest);  
  67.  
  68.         processor.StreamToDisk(context, encoding, path);  
  69.  
  70.         //return RedirectToAction("Index", "Upload");  
  71.         Response.Redirect(Url.Action("Index""Upload"));  
  72.     }  
  73. }  

雖然這里明顯缺少一兩個類,但基本的方法還是講清楚了,看起來和緩存邏輯并沒有太大的不同之處,我們仍然將流緩存到了磁盤,但具體處理方式卻有些不同了,首先,沒有與方法關聯的屬性,謂詞和授權限制都被移除了,使用手動等值取代了,使用手工響應操作而不用ActionFilterAttribute聲明的原因是這些屬性涉及到了一些重要的ASP.NET管道代碼,實際上在我的代碼中,我還特意攔截了原生態的HttpWorkerRequest,因為它不能同時做兩件事情。

#p#

HttpWorkerRequest有VIP訪問傳入的請求,通常它是由ASP.NET本身支持工作的,但我們綁架了請求,然后欺騙剩下的請求,讓它們誤以為前面的請求已經全部得到處理,為了做到這一點,我們需要上面例子中未出現的UploadProcessor類,這個類的職責是物理讀取來自瀏覽器的每個數據塊,然后將其保存到磁盤上,因為上傳的內容被分解成多個部分,UploadProcessor類需要找出內容頭,然后拼接成帶狀數據輸出,這一可以在一個上傳中同時上傳多個文件。

  1. internal class UploadProcessor  
  2. {  
  3.     private byte[] _buffer;  
  4.     private byte[] _boundaryBytes;  
  5.     private byte[] _endHeaderBytes;  
  6.     private byte[] _endFileBytes;  
  7.     private byte[] _lineBreakBytes;  
  8.  
  9.     private const string _lineBreak = "\r\n";  
  10.  
  11.     private readonly Regex _filename =  
  12.         new Regex(@"Content-Disposition:\s*form-data\s*;\s*name\s*=\s*""file""\s*;\s*filename\s*=\s*""(.*)""",  
  13.                   RegexOptions.IgnoreCase | RegexOptions.Compiled);  
  14.  
  15.     private readonly HttpWorkerRequest _workerRequest;  
  16.  
  17.     public UploadProcessor(HttpWorkerRequest workerRequest)  
  18.     {  
  19.         _workerRequest = workerRequest;  
  20.     }  
  21.  
  22.     public void StreamToDisk(IServiceProvider provider, Encoding encoding, string rootPath)  
  23.     {  
  24.         var buffer = new byte[8192];  
  25.  
  26.         if (!_workerRequest.HasEntityBody())  
  27.         {  
  28.             return;  
  29.         }  
  30.  
  31.         var total = _workerRequest.GetTotalEntityBodyLength();  
  32.         var preloaded = _workerRequest.GetPreloadedEntityBodyLength();  
  33.         var loaded = preloaded;  
  34.  
  35.         SetByteMarkers(_workerRequest, encoding);  
  36.  
  37.         var body = _workerRequest.GetPreloadedEntityBody();  
  38.         if (body == null// IE normally does not preload  
  39.         {  
  40.             body = new byte[8192];  
  41.             preloaded = _workerRequest.ReadEntityBody(body, body.Length);  
  42.             loaded = preloaded;  
  43.         }  
  44.  
  45.         var text = encoding.GetString(body);  
  46.         var fileName = _filename.Matches(text)[0].Groups[1].Value;  
  47.         fileName = Path.GetFileName(fileName); // IE captures full user path; chop it  
  48.  
  49.         var path = Path.Combine(rootPath, fileName);  
  50.         var files = new List {fileName};  
  51.         var stream = new FileStream(path, FileMode.Create);  
  52.  
  53.         if (preloaded > 0)  
  54.         {  
  55.             stream = ProcessHeaders(body, stream, encoding, preloaded, files, rootPath);  
  56.         }  
  57.  
  58.         // Used to force further processing (i.e. redirects) to avoid buffering the files again  
  59.         var workerRequest = new StaticWorkerRequest(_workerRequest, body);  
  60.         var field = HttpContext.Current.Request.GetType().GetField("_wr", BindingFlags.NonPublic | BindingFlags.Instance);  
  61.         field.SetValue(HttpContext.Current.Request, workerRequest);  
  62.  
  63.         if (!_workerRequest.IsEntireEntityBodyIsPreloaded())  
  64.         {  
  65.             var received = preloaded;  
  66.             while (total - received >= loaded && _workerRequest.IsClientConnected())  
  67.             {  
  68.                 loaded = _workerRequest.ReadEntityBody(buffer, buffer.Length);  
  69.                 stream = ProcessHeaders(buffer, stream, encoding, loaded, files, rootPath);  
  70.  
  71.                 received += loaded;  
  72.             }  
  73.  
  74.             var remaining = total - received;  
  75.             buffer = new byte[remaining];  
  76.  
  77.             loaded = _workerRequest.ReadEntityBody(buffer, remaining);  
  78.             stream = ProcessHeaders(buffer, stream, encoding, loaded, files, rootPath);  
  79.         }  
  80.  
  81.         stream.Flush();  
  82.         stream.Close();  
  83.         stream.Dispose();  
  84.     }  
  85.  
  86.     private void SetByteMarkers(HttpWorkerRequest workerRequest, Encoding encoding)  
  87.     {  
  88.         var contentType = workerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType);  
  89.         var bufferIndex = contentType.IndexOf("boundary=") + "boundary=".Length;  
  90.         var boundary = String.Concat("--", contentType.Substring(bufferIndex));  
  91.  
  92.         _boundaryBytes = encoding.GetBytes(string.Concat(boundary, _lineBreak));  
  93.         _endHeaderBytes = encoding.GetBytes(string.Concat(_lineBreak, _lineBreak));  
  94.         _endFileBytes = encoding.GetBytes(string.Concat(_lineBreak, boundary, "--", _lineBreak));  
  95.         _lineBreakBytes = encoding.GetBytes(string.Concat(_lineBreak + boundary + _lineBreak));  
  96.     }  
  97.  
  98.     private FileStream ProcessHeaders(byte[] buffer, FileStream stream, Encoding encoding, int count, ICollection files, string rootPath)  
  99.     {  
  100.         buffer = AppendBuffer(buffer, count);  
  101.  
  102.         var startIndex = IndexOf(buffer, _boundaryBytes, 0);  
  103.         if (startIndex != -1)  
  104.         {  
  105.             var endFileIndex = IndexOf(buffer, _endFileBytes, 0);  
  106.             if (endFileIndex != -1)  
  107.             {  
  108.                 var precedingBreakIndex = IndexOf(buffer, _lineBreakBytes, 0);  
  109.                 if (precedingBreakIndex > -1)  
  110.                 {  
  111.                     startIndex = precedingBreakIndex;  
  112.                 }  
  113.  
  114.                 endFileIndex += _endFileBytes.Length;  
  115.  
  116.                 var modified = SkipInput(buffer, startIndex, endFileIndex, ref count);  
  117.                 stream.Write(modified, 0, count);  
  118.             }  
  119.             else 
  120.             {  
  121.                 var endHeaderIndex = IndexOf(buffer, _endHeaderBytes, 0);  
  122.                 if (endHeaderIndex != -1)  
  123.                 {  
  124.                     endHeaderIndex += _endHeaderBytes.Length;  
  125.  
  126.                     var text = encoding.GetString(buffer);  
  127.                     var match = _filename.Match(text);  
  128.  
  129.                     var fileName = match != null ? match.Groups[1].Value : null;  
  130.                     fileName = Path.GetFileName(fileName); // IE captures full user path; chop it  
  131.  
  132.                     if (!string.IsNullOrEmpty(fileName) && !files.Contains(fileName))  
  133.                     {  
  134.                         files.Add(fileName);  
  135.  
  136.                         var filePath = Path.Combine(rootPath, fileName);  
  137.  
  138.                         stream = ProcessNextFile(stream, buffer, count, startIndex, endHeaderIndex, filePath);  
  139.                     }  
  140.                     else 
  141.                     {  
  142.                         var modified = SkipInput(buffer, startIndex, endHeaderIndex, ref count);  
  143.                         stream.Write(modified, 0, count);  
  144.                     }  
  145.                 }  
  146.                 else 
  147.                 {  
  148.                     _buffer = buffer;  
  149.                 }  
  150.             }  
  151.         }  
  152.         else 
  153.         {  
  154.             stream.Write(buffer, 0, count);  
  155.         }  
  156.  
  157.         return stream;  
  158.     }  
  159.  
  160.     private static FileStream ProcessNextFile(FileStream stream, byte[] buffer, int count, int startIndex, int endIndex, string filePath)  
  161.     {  
  162.         var fullCount = count;  
  163.         var endOfFile = SkipInput(buffer, startIndex, count, ref count);  
  164.         stream.Write(endOfFile, 0, count);  
  165.  
  166.         stream.Flush();  
  167.         stream.Close();  
  168.         stream.Dispose();  
  169.  
  170.         stream = new FileStream(filePath, FileMode.Create);  
  171.  
  172.         var startOfFile = SkipInput(buffer, 0, endIndex, ref fullCount);  
  173.         stream.Write(startOfFile, 0, fullCount);  
  174.  
  175.         return stream;  
  176.     }  
  177.  
  178.     private static int IndexOf(byte[] array, IList value, int startIndex)  
  179.     {  
  180.         var index = 0;  
  181.         var start = Array.IndexOf(array, value[0], startIndex);  
  182.  
  183.         if (start == -1)  
  184.         {  
  185.             return -1;  
  186.         }  
  187.  
  188.         while ((start + index) < array.Length)  
  189.         {  
  190.             if (array[start + index] == value[index])  
  191.             {  
  192.                 index++;  
  193.                 if (index == value.Count)  
  194.                 {  
  195.                     return start;  
  196.                 }  
  197.             }  
  198.             else 
  199.             {  
  200.                 start = Array.IndexOf(array, value[0], start + index);  
  201.  
  202.                 if (start != -1)  
  203.                 {  
  204.                     index = 0;  
  205.                 }  
  206.                 else 
  207.                 {  
  208.                     return -1;  
  209.                 }  
  210.             }  
  211.         }  
  212.  
  213.         return -1;  
  214.     }  
  215.  
  216.     private static byte[] SkipInput(byte[] input, int startIndex, int endIndex, ref int count)  
  217.     {  
  218.         var range = endIndex - startIndex;  
  219.         var size = count - range;  
  220.  
  221.         var modified = new byte[size];  
  222.         var modifiedCount = 0;  
  223.  
  224.         for (var i = 0; i < input.Length; i++)  
  225.         {  
  226.             if (i >= startIndex && i < endIndex)  
  227.             {  
  228.                 continue;  
  229.             }  
  230.  
  231.             if (modifiedCount >= size)  
  232.             {  
  233.                 break;  
  234.             }  
  235.  
  236.             modified[modifiedCount] = input[i];  
  237.             modifiedCount++;  
  238.         }  
  239.  
  240.         input = modified;  
  241.         count = modified.Length;  
  242.         return input;  
  243.     }  
  244.  
  245.     private byte[] AppendBuffer(byte[] buffer, int count)  
  246.     {  
  247.         var input = new byte[_buffer == null ? buffer.Length : _buffer.Length + count];  
  248.         if (_buffer != null)  
  249.         {  
  250.             Buffer.BlockCopy(_buffer, 0, input, 0, _buffer.Length);  
  251.         }  
  252.         Buffer.BlockCopy(buffer, 0, input, _buffer == null ? 0 : _buffer.Length, count);  
  253.         _buffer = null;  
  254.  
  255.         return input;  
  256.     }  

在處理代碼的中間位置,你應該注意到了另一個類StaticWorkerRequest,這個類負責欺騙ASP.NET,在點擊提交按鈕時,它欺騙ASP.NET,讓他認為沒有文件上傳,這是必需的,因為當上傳完畢時,如果我們要重定向到所需的頁面時,ASP.NET將會檢查到在HTTP實體主體中仍然有數據,然后會嘗試緩存整個上傳,于是我們兜了一圈又回到了原點,為了避免這種情況,我們必須欺騙HttpWorkerRequest,將它注入到HttpContext中,獲得請求開始部分的StaticWorkerRequest,它是唯一有用的數據。

  1. internal class StaticWorkerRequest : HttpWorkerRequest  
  2. {  
  3.     readonly HttpWorkerRequest _request;  
  4.     private readonly byte[] _buffer;  
  5.  
  6.     public StaticWorkerRequest(HttpWorkerRequest request, byte[] buffer)  
  7.     {  
  8.         _request = request;  
  9.         _buffer = buffer;  
  10.     }  
  11.  
  12.     public override int ReadEntityBody(byte[] buffer, int size)  
  13.     {  
  14.         return 0;  
  15.     }  
  16.  
  17.     public override int ReadEntityBody(byte[] buffer, int offset, int size)  
  18.     {  
  19.         return 0;  
  20.     }  
  21.  
  22.     public override byte[] GetPreloadedEntityBody()  
  23.     {  
  24.         return _buffer;  
  25.     }  
  26.  
  27.     public override int GetPreloadedEntityBody(byte[] buffer, int offset)  
  28.     {  
  29.         Buffer.BlockCopy(_buffer, 0, buffer, offset, _buffer.Length);  
  30.         return _buffer.Length;  
  31.     }  
  32.  
  33.     public override int GetPreloadedEntityBodyLength()  
  34.     {  
  35.         return _buffer.Length;  
  36.     }  
  37.  
  38.     public override int GetTotalEntityBodyLength()  
  39.     {  
  40.         return _buffer.Length;  
  41.     }  
  42.  
  43.     public override string GetKnownRequestHeader(int index)  
  44.     {  
  45.         return index == HeaderContentLength  
  46.                    ? "0" 
  47.                    : _request.GetKnownRequestHeader(index);  
  48.     }  
  49.  
  50.     // All other methods elided, they're just passthrough  

使用StaticWorkerRequest建立虛假的聲明,現在你可以在ASP.NET MVC中通過直接訪問數據流上傳大文件,使用這個代碼作為開始,你可以很容易地保存過程數據,并使用Ajax調用另一個控制器行為展示其進度,將大文件緩存到一個臨時區域,可以實現斷點續傳,不用再等待ASP.NET進程將整個文件緩存到磁盤上,同樣,保存文件時也不用消耗另存為方法那么多的內存了。

使用StaticWorkerRequest,內存消耗更平穩 
圖 2: 內存消耗更平穩

 

【更多關于ASP.NET上傳文件的介紹】

  1. 專訪微軟MVP衣明志:走進ASP.NET MVC 2框架開發
  2. ASP.NET大文件上傳方法淺析
  3. ASP.NET上傳文件面面觀
  4. ASP.NET上傳文件控件實例詳解
  5. ASP.NET多附件上傳和附件編輯的實現
責任編輯:佚名 來源: 51CTO.com
相關推薦

2009-07-21 15:38:31

2009-07-20 16:09:39

2009-07-21 16:05:58

ASP.NET大文件上

2009-07-22 10:13:31

異步ActionASP.NET MVC

2009-03-06 10:28:30

MVCASP.NET異步Action

2009-07-20 15:44:32

ASP.NET MVC

2009-07-31 12:43:59

ASP.NET MVC

2009-07-24 13:20:44

MVC框架ASP.NET

2009-06-12 09:24:34

ASP.NET窗體ASP.NET MVC

2009-12-21 10:05:10

ASP.NET MVC

2015-03-03 13:15:19

ASP.NET大文件下載實現思路

2009-02-17 09:22:14

ActionMVCASP.NET

2009-02-16 10:05:11

ActionMVCASP.NET

2024-05-20 13:06:18

2009-07-22 16:02:39

ASP.NET MVCPagedList

2009-07-28 14:47:18

ASP.NET MVC

2017-03-06 11:13:57

ASP.NETCoreMVC

2009-07-22 13:16:04

MvcAjaxPaneASP.NET MVC

2009-07-29 10:02:49

ASP.NET上傳

2009-09-24 09:26:22

ASP.NET MVC
點贊
收藏

51CTO技術棧公眾號

国产精品99一区二区| 自拍在线观看| 成人精品视频一区二区三区 | 国产精品99久久久久久成人| 999久久久国产999久久久| 亚洲成年人网站在线观看| 秋霞毛片久久久久久久久| 国产精品热久久| 一本久久综合| 欧美成人免费在线视频| 亚洲码无人客一区二区三区| 免费一级欧美在线大片| 色哟哟一区二区三区| 免费观看国产视频在线| 国产三级在线免费| 国产成人亚洲综合a∨婷婷图片 | 国产精品99久久免费| 欧美视频裸体精品| 九一免费在线观看| 成年人在线看| 91麻豆高清视频| 电影午夜精品一区二区三区| 在线亚洲欧美日韩| 久久国产精品99国产| 色综合久久久888| 黄色激情小视频| 久久99国产精品视频| 精品少妇一区二区三区| 亚洲网中文字幕| 国产黄色精品| 在线亚洲人成电影网站色www| 精品无码一区二区三区爱欲| 蜜桃视频在线观看免费视频网站www | 青青久久av北条麻妃黑人| 青青草国产在线观看| 97视频精品| 国产亚洲综合久久| 欧美狂猛xxxxx乱大交3| 天堂网av成人| 亚洲激情中文字幕| av漫画在线观看| 日本亚洲视频| 日韩精品一区二区三区在线 | 国产在线不卡一区二区三区| 91国偷自产一区二区使用方法| 浮妇高潮喷白浆视频| sis001亚洲原创区| 午夜欧美2019年伦理| 国产乱子伦精品无码专区| gogo在线观看| 亚洲激情自拍偷拍| 毛片在线视频观看| 性爱视频在线播放| 夜夜操天天操亚洲| 欧美日韩福利在线| 白浆视频在线观看| 狠狠躁夜夜躁久久躁别揉| 欧美 日韩 亚洲 一区| av白虎一区| 欧美日韩免费区域视频在线观看| 欧美日韩一道本| 少妇视频一区| 在线精品视频免费观看| 天天视频天天爽| 国产精品成人**免费视频| 欧美一区二区三区免费| 亚洲妇女无套内射精| 懂色av一区二区| 精品久久国产老人久久综合| 韩国三级hd两男一女| 欧美绝顶高潮抽搐喷水合集| 亚洲视频免费一区| 长河落日免费高清观看| 重囗味另类老妇506070| 久久久之久亚州精品露出| 五月婷婷中文字幕| 日韩成人精品在线观看| 91精品国产自产在线老师啪| www.色呦呦| 2024国产精品| 亚洲精品成人三区| dy888亚洲精品一区二区三区| 亚洲一区视频在线观看视频| aⅴ在线免费观看| 亚洲青青一区| 亚洲国产第一页| 久久中文字幕精品| 国产精品v亚洲精品v日韩精品| 久久乐国产精品| 自拍偷拍精品视频| 国产 欧美在线| 蜜桃久久精品乱码一区二区| 免费在线你懂的| 婷婷成人综合网| 国产原创精品在线| 国产高清日韩| 亚洲视频在线看| 欧美日韩精品亚洲精品| 久久久国产精品一区二区中文| 91在线观看免费网站| 天天操天天干天天插| 国产精品久久午夜夜伦鲁鲁| 日韩中字在线观看| 香蕉久久一区| 国产丝袜高跟一区| 波多野结衣爱爱视频| 亚洲女优在线| 国产二区一区| 免费人成在线观看播放视频| 欧美午夜精品久久久久久久| 一级黄色高清视频| 精品精品久久| 777国产偷窥盗摄精品视频| 亚洲图片在线播放| 91视频观看免费| 日本一本中文字幕| 日韩深夜福利网站| 国产一区二区三区18| 一级片免费网址| 国产福利91精品| 中文字幕一区二区三区四区五区人 | 曰本一区二区三区视频| 欧美精品videosex牲欧美| 在线观看中文字幕网站| 91麻豆文化传媒在线观看| 99亚洲国产精品| 国产精品久久久久久妇女| 日韩成人高清在线| 免费一级肉体全黄毛片| 九色综合国产一区二区三区| 欧洲精品久久| 色综合亚洲图丝熟| 亚洲国产精品99| 青娱乐国产在线| 黄网站免费久久| 亚洲欧洲日韩综合二区| 日韩视频网站在线观看| 亚洲精品国产suv| 久久精品99久久久久久| 国产麻豆午夜三级精品| 日韩 欧美 自拍| 中文字幕日本一区| 久久久999精品视频| ,一级淫片a看免费| 国产精品欧美极品| 日韩中文字幕a| 国产精品国内免费一区二区三区| 国产在线观看一区二区三区| 在线日本视频| 欧美男男青年gay1069videost| 91动漫免费网站| 精品系列免费在线观看| www.午夜色| 日本超碰一区二区| 欧美噜噜久久久xxx| 亚洲成a人片77777精品| 亚洲一区在线电影| 日韩aaaaa| 六月天综合网| 亚洲女人毛片| 精品久久亚洲| 国内精品一区二区三区| 视频国产在线观看| 欧美中文字幕一区二区三区 | 中文字幕人妻一区| 国产日韩精品视频一区二区三区| 噜噜噜噜噜久久久久久91| 亚洲播播91| 日韩亚洲综合在线| 亚洲精品久久久久久动漫器材一区| 亚洲一区二区精品3399| 亚洲 欧美 日韩在线| 亚洲自拍另类| 一区二区三区四区五区精品| 亚洲1区在线| 欧美在线播放视频| 免费观看久久久久| 精品久久久久久久久久久久包黑料| 国产成人一级片| 国产精品二区一区二区aⅴ污介绍| 香蕉网在线视频| 国产精品亚洲产品| 一区二区三区国| 精品伊人久久久| 国产精品一区二区在线| 青青草视频在线免费直播| 亚洲精品中文字幕av| 一级黄色片免费看| 午夜精品123| 日本激情视频一区二区三区| 国产一区激情在线| 日韩人妻无码精品久久久不卡| 欧美欧美黄在线二区| **亚洲第一综合导航网站| 妞干网免费在线视频| 久久精品99久久久香蕉| 婷婷亚洲一区二区三区| 欧美美女黄视频| 五月天综合激情网| 亚洲同性同志一二三专区| 亚洲色图14p| 国产精品一区二区三区乱码| 一本大道熟女人妻中文字幕在线| 91精品国产91久久久久久黑人| 久久精品国产精品青草色艺| 91精品国产一区二区在线观看| 2019中文字幕在线免费观看| aa在线视频| 中文亚洲视频在线| 国产毛片毛片毛片毛片毛片| 日韩欧美视频一区二区三区| 精品午夜福利视频| 中文字幕在线观看一区| 中日韩精品一区二区三区| 国产精品一区久久久久| xxww在线观看| 久色成人在线| 日本福利视频在线| 精品av久久久久电影| 国产又爽又黄ai换脸| 国产免费av一区二区三区| 国产亚洲二区| 四虎在线精品| 国产精品久久中文| 日本成人三级电影| 97精品久久久| sm在线播放| 欧美激情在线观看| 人人澡人人添人人爽一区二区| 色偷偷偷亚洲综合网另类| 狠狠狠综合7777久夜色撩人| 精品伊人久久97| 无码国产精品一区二区色情男同| 欧美成人r级一区二区三区| 97超碰人人草| 69堂成人精品免费视频| 国产精品老熟女视频一区二区| 色老综合老女人久久久| 无码人妻久久一区二区三区不卡| 欧美性xxxx极品高清hd直播| 欧美特黄aaaaaa| 欧美性猛交xxxx黑人| 在线观看国产亚洲| 精品日韩中文字幕| 欧美国产成人精品一区二区三区| 岛国av午夜精品| 中文字幕国产在线观看| 色综合久久中文字幕| 区一区二在线观看| 欧美最新大片在线看| 中文字幕在线2018| 欧美嫩在线观看| 国产黄色片免费观看| 精品国产网站在线观看| 好吊色在线观看| 亚洲精品mp4| 久久电影视频| 日韩视频亚洲视频| 日本乱理伦在线| 久久人人爽人人| 亚洲女色av| 国产精品女人网站| 99re8精品视频在线观看| 亚洲影视中文字幕| 另类ts人妖一区二区三区| 国产一区二区中文字幕免费看| 日本在线中文字幕一区| 色姑娘综合av| 亚洲综合小说| 久久成人福利视频| 久久综合导航| 四虎1515hh.com| 91丝袜美腿高跟国产极品老师 | 高清av在线| 美女撒尿一区二区三区| 第一中文字幕在线| 国产不卡精品视男人的天堂 | 精品日本一区二区三区在线观看| 在线成人动漫av| xxxxxx在线观看| 久久精品男女| 爱情岛论坛亚洲自拍| 久久中文字幕电影| 男人在线观看视频| 午夜不卡av在线| 91九色蝌蚪91por成人| 欧美精品一区二区三区高清aⅴ | 久久久精品高清| 本田岬高潮一区二区三区| 黄色aaa视频| 亚洲综合一区二区| 97人妻精品视频一区| 91精品国产91久久久久久最新毛片| 熟妇人妻av无码一区二区三区| 中文字幕国产亚洲2019| 国产偷倩在线播放| 国产精品成人一区二区| 国产suv精品一区| 亚洲一二三区精品| 99riav国产精品| 国产探花在线观看视频| 久久午夜色播影院免费高清| 曰本女人与公拘交酡| 在线精品视频免费观看| 内射后入在线观看一区| 久久精品视频在线| 色婷婷综合久久久中字幕精品久久 | 亚洲天堂中文字幕在线| 国产丝袜一区二区三区| 最新日本在线观看| 国产精品视频午夜| 亚洲制服一区| 久久国产精品视频在线观看| 国产精品中文欧美| 青青青手机在线视频| 欧美日韩中文在线| 好吊视频一二三区| 九九热最新视频//这里只有精品| 欧美日一区二区三区| 久久精品国产美女| 亚洲精品九九| 在线观看一区二区三区四区| 亚洲欧洲成人精品av97| 特级西西444www高清大视频| 精品视频久久久久久| 51漫画成人app入口| 99在线热播| 欧美~级网站不卡| 欧洲美女亚洲激情| 国产精品久久久久久久岛一牛影视| 日本中文字幕在线| 日韩精品视频中文在线观看| 成人福利电影| 国产精品露出视频| 激情成人亚洲| 亚洲图片欧美另类| 亚洲国产人成综合网站| 亚洲第一页视频| 久久久视频免费观看| 成人免费在线电影网| 免费的一级黄色片| 成人做爰69片免费看网站| 精品一区在线视频| 精品福利在线导航| 男人av在线播放| 欧美日韩在线精品| 免费在线看成人av| 国产精品成人69xxx免费视频| 欧美男男青年gay1069videost| 毛片在线看片| 91手机在线播放| 亚洲婷婷免费| 日本xxxx裸体xxxx| 欧美在线一区二区三区| 日本暖暖在线视频| 亚洲一区二区久久久久久久| 欧美福利专区| 中国黄色片视频| 高跟丝袜欧美一区| av在线播放av| 亚洲xxx视频| 日韩午夜电影| 亚洲精品一区二区三区影院忠贞| 欧美色综合久久| 二区三区在线观看| 国精产品99永久一区一区| 久久av在线| 国产精品酒店视频| 欧美第一区第二区| 亚洲欧美小说色综合小说一区| 日韩一二三区不卡在线视频| 久久99精品国产麻豆不卡| 69av视频在线| 亚洲精品日韩久久久| 四虎国产精品成人免费影视| 老司机午夜网站| 久久人人97超碰com| 亚洲资源在线播放| 久久久欧美精品| 精品欧美激情在线观看| 国产精品嫩草影视| 精品国产户外野外| 亚洲s色大片| 国产区一区二区三区| 男人的j进女人的j一区| 久久久国产成人| 在线看福利67194| 成人性生交大片免费看96| 久久综合久久色| 亚洲自拍偷拍av| sese在线视频| 国产在线观看一区| 精品一区二区三区免费视频| 国产成人无码精品久久久久| 日韩一区视频在线| 全国精品免费看| 少妇极品熟妇人妻无码| 在线免费视频一区二区| 2019中文字幕在线电影免费| 亚洲一区二区三区精品视频|