<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # History [[WebApi] 搗鼓一個資源管理器--文件下載](http://blog.csdn.net/qiujuer/article/details/41621781) [[WebApi] 搗鼓一個資源管理器--多文件上傳](http://blog.csdn.net/qiujuer/article/details/41675299) [[WebApi] 搗鼓一個資源管理器--多文件上傳+數據庫輔助](http://blog.csdn.net/qiujuer/article/details/41721165) # In This ##### 序 文件可以上傳了,下一步就是文件的訪問了;只有文件上傳沒有文件訪問。那么數據就是浪費! ##### 目標 1. 文件訪問要能通過上一章文件的那些東西訪問磁盤中的文件 2. 文件要能區分圖片文件和其他文件;分別是直接打開和附件保存 3. 文件要能有瀏覽器緩存,如打開同一個圖片不用重復從服務器加載 ##### 分析 1. 文件的訪問這個當然要借助上一章中在數據庫中保存的數據進行組合成文件返回流 2. 直接打開和附件無非就是設置返回頭中的**Disposition:inline/attachment** 3. 瀏覽器緩存這個就是設置返回頭中的緩存信息了 # CodeTime ##### 改動 ![](https://box.kancloud.cn/2016-01-11_5693565c1c0e2.jpg) 這次簡單,只更改了一個文件;不過更改較大。 ##### 流程 ![](https://box.kancloud.cn/2016-01-11_5693565c2f1c3.jpg) 簡單畫了一個;湊合著看啊;就是一個請求來了,先查找數據庫,找到該文件的信息;根據這些信息去查找文件。然后返回;沒有找到數據 或者沒有找到文件都直接返回404。 ##### Get() ~~~ /// <summary> /// Get File /// </summary> /// <param name="name">MD5 Name</param> /// <returns>File</returns> [HttpGet] [Route("{Id}")] public async Task<HttpResponseMessage> Get(string Id) { // Return 304 // 判斷是否含有Tag,有就返回瀏覽器緩存 var tag = Request.Headers.IfNoneMatch.FirstOrDefault(); if (Request.Headers.IfModifiedSince.HasValue && tag != null && tag.Tag.Length > 0) return new HttpResponseMessage(HttpStatusCode.NotModified); //查找該文件 Resource model = await db.Resources.FindAsync(Id); //未找到文件 if (model == null) return new HttpResponseMessage(HttpStatusCode.BadRequest); // 加載文件信息 FileInfo info = new FileInfo(Path.Combine(ROOT_PATH, model.Folder, model.Id)); // 文件沒有找到 if (!info.Exists) return new HttpResponseMessage(HttpStatusCode.BadRequest); FileStream file = null; try { // 打開文件 file = new FileStream(info.FullName, FileMode.Open, FileAccess.Read, FileShare.Read); // 新建http響應 HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); // 設置頭部信息 // GetDisposition() 用于決定文件是直接打開還是提示下載 // 一般來說圖片文件就直接打開,其他文件就提示下載 ContentDispositionHeaderValue disposition = new ContentDispositionHeaderValue(GetDisposition(model.Type)); // 設置文件名+擴展 disposition.FileName = string.Format("{0}.{1}", model.Name, model.Type); // 文件名 disposition.Name = model.Name; // 文件大小 disposition.Size = file.Length; if (file.Length < MEMORY_SIZE) { // 如果 小于64MB 就直接拷貝到內存流中返回 // Copy To Memory And Close. byte[] bytes = new byte[file.Length]; await file.ReadAsync(bytes, 0, (int)file.Length); file.Close(); MemoryStream ms = new MemoryStream(bytes); result.Content = new ByteArrayContent(ms.ToArray()); } else { // 如果不是就直接打包為文件流返回 result.Content = new StreamContent(file); } // 設置文件在網絡中的ContentType // GetContentType() 方法是根據擴展名去查找字典 // 字典中我收集了大概150種,基本足夠使用了 result.Content.Headers.ContentType = new MediaTypeHeaderValue(GetContentType(model.Type)); result.Content.Headers.ContentDisposition = disposition; // 設置瀏覽器緩存相關 // 設置緩存Expires result.Content.Headers.Expires = new DateTimeOffset(DateTime.Now).AddHours(1); // 緩存最后修改時間 result.Content.Headers.LastModified = new DateTimeOffset(model.Published); // 緩存控制 result.Headers.CacheControl = new CacheControlHeaderValue() { Public = true, MaxAge = TimeSpan.FromHours(1) }; // 設置ETag,這里的ETag為了方便就直接使用MD5值 result.Headers.ETag = new EntityTagHeaderValue(string.Format("\"{0}\"", model.Id)); // 返回請求 return result; } catch { if (file != null) { file.Close(); } } return new HttpResponseMessage(HttpStatusCode.BadRequest); } ~~~ **Get()**方法是這次的精髓部分;其中的作用也都加上了注釋了。 ##### ResourceApiController.cs ~~~ using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web; using System.Web.Http; using System.Web.Http.Description; using WebResource.Models; namespace WebResource.Controllers { [RoutePrefix("Res")] public class ResourceApiController : ApiController { // 操作 數據庫 private WebResourceContext db = new WebResourceContext(); // 最大內存使用大小 private static readonly long MEMORY_SIZE = 64 * 1024 * 1024; // 文件默認存儲位置 private static readonly string ROOT_PATH = HttpContext.Current.Server.MapPath("~/App_Data/"); // ContentType字典 private static Dictionary<string, string> CONTENT_TYPE = null; /// <summary> /// 初始化字典 /// </summary> static ResourceApiController() { CONTENT_TYPE = new Dictionary<string, string>(); CONTENT_TYPE.Add("ex", "application/andrew-inset"); CONTENT_TYPE.Add("hqx", "application/mac-binhex40"); CONTENT_TYPE.Add("cpt", "application/mac-compactpro"); CONTENT_TYPE.Add("doc", "application/msword"); CONTENT_TYPE.Add("docx", "application/msword"); CONTENT_TYPE.Add("bin", "application/octet-stream"); CONTENT_TYPE.Add("dms", "application/octet-stream"); CONTENT_TYPE.Add("lha", "application/octet-stream"); CONTENT_TYPE.Add("lzh", "application/octet-stream"); CONTENT_TYPE.Add("exe", "application/octet-stream"); CONTENT_TYPE.Add("class", "application/octet-stream"); CONTENT_TYPE.Add("so", "application/octet-stream"); CONTENT_TYPE.Add("dll", "application/octet-stream"); CONTENT_TYPE.Add("oda", "application/oda"); CONTENT_TYPE.Add("pdf", "application/pdf"); CONTENT_TYPE.Add("ai", "application/postscript"); CONTENT_TYPE.Add("eps", "application/postscript"); CONTENT_TYPE.Add("ps", "application/postscript"); CONTENT_TYPE.Add("smi", "application/smil"); CONTENT_TYPE.Add("smil", "application/smil"); CONTENT_TYPE.Add("mif", "application/vnd.mif"); CONTENT_TYPE.Add("xls", "application/vnd.ms-excel"); CONTENT_TYPE.Add("xlsx", "application/vnd.ms-excel"); CONTENT_TYPE.Add("ppt", "application/vnd.ms-powerpoint"); CONTENT_TYPE.Add("wbxml", "application/vnd.wap.wbxml"); CONTENT_TYPE.Add("wmlc", "application/vnd.wap.wmlc"); CONTENT_TYPE.Add("wmlsc", "application/vnd.wap.wmlscriptc"); CONTENT_TYPE.Add("bcpio", "application/x-bcpio"); CONTENT_TYPE.Add("vcd", "application/x-cdlink"); CONTENT_TYPE.Add("pgn", "application/x-chess-pgn"); CONTENT_TYPE.Add("cpio", "application/x-cpio"); CONTENT_TYPE.Add("csh", "application/x-csh"); CONTENT_TYPE.Add("dcr", "application/x-director"); CONTENT_TYPE.Add("dir", "application/x-director"); CONTENT_TYPE.Add("dxr", "application/x-director"); CONTENT_TYPE.Add("dvi", "application/x-dvi"); CONTENT_TYPE.Add("spl", "application/x-futuresplash"); CONTENT_TYPE.Add("gtar", "application/x-gtar"); CONTENT_TYPE.Add("hdf", "application/x-hdf"); CONTENT_TYPE.Add("js", "application/x-javascript"); CONTENT_TYPE.Add("skp", "application/x-koan"); CONTENT_TYPE.Add("skd", "application/x-koan"); CONTENT_TYPE.Add("skt", "application/x-koan"); CONTENT_TYPE.Add("skm", "application/x-koan"); CONTENT_TYPE.Add("latex", "application/x-latex"); CONTENT_TYPE.Add("nc", "application/x-netcdf"); CONTENT_TYPE.Add("cdf", "application/x-netcdf"); CONTENT_TYPE.Add("sh", "application/x-sh"); CONTENT_TYPE.Add("shar", "application/x-shar"); CONTENT_TYPE.Add("swf", "application/x-shockwave-flash"); CONTENT_TYPE.Add("flv", "application/x-shockwave-flash"); CONTENT_TYPE.Add("sit", "application/x-stuffit"); CONTENT_TYPE.Add("sv4cpio", "application/x-sv4cpio"); CONTENT_TYPE.Add("sv4crc", "application/x-sv4crc"); CONTENT_TYPE.Add("tar", "application/x-tar"); CONTENT_TYPE.Add("tcl", "application/x-tcl"); CONTENT_TYPE.Add("tex", "application/x-tex"); CONTENT_TYPE.Add("texinfo", "application/x-texinfo"); CONTENT_TYPE.Add("texi", "application/x-texinfo"); CONTENT_TYPE.Add("t", "application/x-troff"); CONTENT_TYPE.Add("tr", "application/x-troff"); CONTENT_TYPE.Add("roff", "application/x-troff"); CONTENT_TYPE.Add("man", "application/x-troff-man"); CONTENT_TYPE.Add("me", "application/x-troff-me"); CONTENT_TYPE.Add("ms", "application/x-troff-ms"); CONTENT_TYPE.Add("ustar", "application/x-ustar"); CONTENT_TYPE.Add("src", "application/x-wais-source"); CONTENT_TYPE.Add("xhtml", "application/xhtml+xml"); CONTENT_TYPE.Add("xht", "application/xhtml+xml"); CONTENT_TYPE.Add("zip", "application/zip"); CONTENT_TYPE.Add("rar", "application/zip"); CONTENT_TYPE.Add("gz", "application/x-gzip"); CONTENT_TYPE.Add("bz2", "application/x-bzip2"); CONTENT_TYPE.Add("au", "audio/basic"); CONTENT_TYPE.Add("snd", "audio/basic"); CONTENT_TYPE.Add("mid", "audio/midi"); CONTENT_TYPE.Add("midi", "audio/midi"); CONTENT_TYPE.Add("kar", "audio/midi"); CONTENT_TYPE.Add("mpga", "audio/mpeg"); CONTENT_TYPE.Add("mp2", "audio/mpeg"); CONTENT_TYPE.Add("mp3", "audio/mpeg"); CONTENT_TYPE.Add("aif", "audio/x-aiff"); CONTENT_TYPE.Add("aiff", "audio/x-aiff"); CONTENT_TYPE.Add("aifc", "audio/x-aiff"); CONTENT_TYPE.Add("m3u", "audio/x-mpegurl"); CONTENT_TYPE.Add("rmm", "audio/x-pn-realaudio"); CONTENT_TYPE.Add("rmvb", "audio/x-pn-realaudio"); CONTENT_TYPE.Add("ram", "audio/x-pn-realaudio"); CONTENT_TYPE.Add("rm", "audio/x-pn-realaudio"); CONTENT_TYPE.Add("rpm", "audio/x-pn-realaudio-plugin"); CONTENT_TYPE.Add("ra", "audio/x-realaudio"); CONTENT_TYPE.Add("wav", "audio/x-wav"); CONTENT_TYPE.Add("wma", "audio/x-wma"); CONTENT_TYPE.Add("pdb", "chemical/x-pdb"); CONTENT_TYPE.Add("xyz", "chemical/x-xyz"); CONTENT_TYPE.Add("bmp", "image/bmp"); CONTENT_TYPE.Add("gif", "image/gif"); CONTENT_TYPE.Add("ief", "image/ief"); CONTENT_TYPE.Add("jpeg", "image/jpeg"); CONTENT_TYPE.Add("jpg", "image/jpeg"); CONTENT_TYPE.Add("jpe", "image/jpeg"); CONTENT_TYPE.Add("png", "image/png"); CONTENT_TYPE.Add("tiff", "image/tiff"); CONTENT_TYPE.Add("tif", "image/tiff"); CONTENT_TYPE.Add("djvu", "image/vnd.djvu"); CONTENT_TYPE.Add("djv", "image/vnd.djvu"); CONTENT_TYPE.Add("wbmp", "image/vnd.wap.wbmp"); CONTENT_TYPE.Add("ras", "image/x-cmu-raster"); CONTENT_TYPE.Add("pnm", "image/x-portable-anymap"); CONTENT_TYPE.Add("pbm", "image/x-portable-bitmap"); CONTENT_TYPE.Add("pgm", "image/x-portable-graymap"); CONTENT_TYPE.Add("ppm", "image/x-portable-pixmap"); CONTENT_TYPE.Add("rgb", "image/x-rgb"); CONTENT_TYPE.Add("xbm", "image/x-xbitmap"); CONTENT_TYPE.Add("xpm", "image/x-xpixmap"); CONTENT_TYPE.Add("xwd", "image/x-xwindowdump"); CONTENT_TYPE.Add("igs", "model/iges"); CONTENT_TYPE.Add("iges", "model/iges"); CONTENT_TYPE.Add("msh", "model/mesh"); CONTENT_TYPE.Add("mesh", "model/mesh"); CONTENT_TYPE.Add("silo", "model/mesh"); CONTENT_TYPE.Add("wrl", "model/vrml"); CONTENT_TYPE.Add("vrml", "model/vrml"); CONTENT_TYPE.Add("css", "text/css"); CONTENT_TYPE.Add("html", "text/html"); CONTENT_TYPE.Add("htm", "text/html"); CONTENT_TYPE.Add("asc", "text/plain"); CONTENT_TYPE.Add("txt", "text/plain"); CONTENT_TYPE.Add("rtx", "text/richtext"); CONTENT_TYPE.Add("rtf", "text/rtf"); CONTENT_TYPE.Add("sgml", "text/sgml"); CONTENT_TYPE.Add("sgm", "text/sgml"); CONTENT_TYPE.Add("tsv", "text/tab-separated-values"); CONTENT_TYPE.Add("wml", "text/vnd.wap.wml"); CONTENT_TYPE.Add("wmls", "text/vnd.wap.wmlscript"); CONTENT_TYPE.Add("etx", "text/x-setext"); CONTENT_TYPE.Add("xsl", "text/xml"); CONTENT_TYPE.Add("xml", "text/xml"); CONTENT_TYPE.Add("mpeg", "video/mpeg"); CONTENT_TYPE.Add("mpg", "video/mpeg"); CONTENT_TYPE.Add("mpe", "video/mpeg"); CONTENT_TYPE.Add("qt", "video/quicktime"); CONTENT_TYPE.Add("mov", "video/quicktime"); CONTENT_TYPE.Add("mxu", "video/vnd.mpegurl"); CONTENT_TYPE.Add("avi", "video/x-msvideo"); CONTENT_TYPE.Add("movie", "video/x-sgi-movie"); CONTENT_TYPE.Add("wmv", "video/x-ms-wmv"); CONTENT_TYPE.Add("asf", "video/x-ms-asf"); CONTENT_TYPE.Add("ice", "x-conference/x-cooltalk"); } /// <summary> /// Get ContentType /// </summary> /// <param name="type">Type</param> /// <returns>ContentType</returns> private static string GetContentType(string type) { // 獲取文件對應的ContentType try { string contentType = CONTENT_TYPE[type]; if (contentType != null) return contentType; } catch { } return "application/octet-stream" + type; } /// <summary> /// Get ContentDisposition /// </summary> /// <param name="type">Type</param> /// <returns>ContentDisposition</returns> private static string GetDisposition(string type) { // 判斷使用瀏覽器打開還是附件模式 if (GetContentType(type).StartsWith("image")) { return "inline"; } return "attachment"; } /// <summary> /// Get File /// </summary> /// <param name="name">MD5 Name</param> /// <returns>File</returns> [HttpGet] [Route("{Id}")] public async Task<HttpResponseMessage> Get(string Id) { // Return 304 // 判斷是否含有Tag,有就返回瀏覽器緩存 var tag = Request.Headers.IfNoneMatch.FirstOrDefault(); if (Request.Headers.IfModifiedSince.HasValue && tag != null && tag.Tag.Length > 0) return new HttpResponseMessage(HttpStatusCode.NotModified); //查找該文件 Resource model = await db.Resources.FindAsync(Id); //未找到文件 if (model == null) return new HttpResponseMessage(HttpStatusCode.BadRequest); // 加載文件信息 FileInfo info = new FileInfo(Path.Combine(ROOT_PATH, model.Folder, model.Id)); // 文件沒有找到 if (!info.Exists) return new HttpResponseMessage(HttpStatusCode.BadRequest); FileStream file = null; try { // 打開文件 file = new FileStream(info.FullName, FileMode.Open, FileAccess.Read, FileShare.Read); // 新建http響應 HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); // 設置頭部信息 // GetDisposition() 用于決定文件是直接打開還是提示下載 // 一般來說圖片文件就直接打開,其他文件就提示下載 ContentDispositionHeaderValue disposition = new ContentDispositionHeaderValue(GetDisposition(model.Type)); // 設置文件名+擴展 disposition.FileName = string.Format("{0}.{1}", model.Name, model.Type); // 文件名 disposition.Name = model.Name; // 文件大小 disposition.Size = file.Length; if (file.Length < MEMORY_SIZE) { // 如果 小于64MB 就直接拷貝到內存流中返回 // Copy To Memory And Close. byte[] bytes = new byte[file.Length]; await file.ReadAsync(bytes, 0, (int)file.Length); file.Close(); MemoryStream ms = new MemoryStream(bytes); result.Content = new ByteArrayContent(ms.ToArray()); } else { // 如果不是就直接打包為文件流返回 result.Content = new StreamContent(file); } // 設置文件在網絡中的ContentType // GetContentType() 方法是根據擴展名去查找字典 // 字典中我收集了大概150種,基本足夠使用了 result.Content.Headers.ContentType = new MediaTypeHeaderValue(GetContentType(model.Type)); result.Content.Headers.ContentDisposition = disposition; // 設置瀏覽器緩存相關 // 設置緩存Expires result.Content.Headers.Expires = new DateTimeOffset(DateTime.Now).AddHours(1); // 緩存最后修改時間 result.Content.Headers.LastModified = new DateTimeOffset(model.Published); // 緩存控制 result.Headers.CacheControl = new CacheControlHeaderValue() { Public = true, MaxAge = TimeSpan.FromHours(1) }; // 設置ETag,這里的ETag為了方便就直接使用MD5值 result.Headers.ETag = new EntityTagHeaderValue(string.Format("\"{0}\"", model.Id)); // 返回請求 return result; } catch { if (file != null) { file.Close(); } } return new HttpResponseMessage(HttpStatusCode.BadRequest); } /// <summary> /// Post File /// </summary> /// <param name="Id">Md5</param> /// <returns>Resource</returns> [HttpPost] [Route("Upload/{Id?}")] [ResponseType(typeof(Resource))] public async Task<IHttpActionResult> Post(string Id = null) { List<Resource> resources = new List<Resource>(); // multipart/form-data var provider = new MultipartMemoryStreamProvider(); await Request.Content.ReadAsMultipartAsync(provider); foreach (var item in provider.Contents) { if (item.Headers.ContentDisposition.FileName != null) { //Strem var ms = item.ReadAsStreamAsync().Result; using (var br = new BinaryReader(ms)) { if (ms.Length <= 0) break; var data = br.ReadBytes((int)ms.Length); //Md5 string id = HashUtils.GetMD5Hash(data); Resource temp = await db.Resources.FindAsync(id); if (temp == null) { //Create Resource resource = new Resource(); resource.Id = id; resource.Size = ms.Length; resource.Cursor = resource.Size; resource.Published = DateTime.Now; //Info FileInfo info = new FileInfo(item.Headers.ContentDisposition.FileName.Replace("\"", "")); resource.Type = info.Extension.Substring(1).ToLower(); resource.Name = info.Name.Substring(0, info.Name.LastIndexOf(".")); //Relative resource.Folder = DateTime.Now.ToString("yyyyMM/dd/", DateTimeFormatInfo.InvariantInfo); //Write try { string dirPath = Path.Combine(ROOT_PATH, resource.Folder); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } File.WriteAllBytes(Path.Combine(dirPath, resource.Id), data); //Save To Datebase db.Resources.Add(resource); await db.SaveChangesAsync(); temp = await db.Resources.FindAsync(resource.Id); } catch { } } if (temp != null) resources.Add(temp); } } } if (resources.Count == 0) return BadRequest(); else if (resources.Count == 1) return Ok(resources.FirstOrDefault()); else return Ok(resources); } } } ~~~ 這個是修改后的**API**文件,**Post**相對上一章沒有進行修改;添加了**Get**,和其他幾個方法以及變量。 # RunTime ##### Api ![](https://box.kancloud.cn/2016-01-11_5693565c77957.jpg) 運行之后首先來看看現在的API,一個是上傳,一個是訪問;簡單吧? ##### Home/Upload ![](https://box.kancloud.cn/2016-01-11_5693565c8eb94.jpg) 上傳兩個,一個圖片一個Zip ![](https://box.kancloud.cn/2016-01-11_5693565cb3b59.jpg) 可以看見返回了兩個文件的信息,分別記住兩個文件的ID,來訪問一下試試。 ##### Image ![](https://box.kancloud.cn/2016-01-11_5693565cca08b.jpg) 可以看見圖片是直接打開在瀏覽器中的;下面來看看**Zip**的文件咋樣。 ![](https://box.kancloud.cn/2016-01-11_5693565ce62e0.jpg) 可以看見是以下載文件的方式返回的。 ##### 請求返回 ###### Zip ![](https://box.kancloud.cn/2016-01-11_5693565d1346a.jpg) 通過瀏覽器調試,我們可以看見Zip文件的返回信息與上面Get方法中設置的參數是一樣的;代表了方法正確執行。 ###### Image ![](https://box.kancloud.cn/2016-01-11_5693565d281d7.jpg) 可以看見圖片的是以**?Inline**?的形式打開的;所以是在瀏覽器中直接顯示。 再次請求圖片: ![](https://box.kancloud.cn/2016-01-11_5693565d426cb.jpg) 通過再次請求圖片;可以看見服務器返回的是304.意思就是瀏覽器自己使用自己的緩存信息;無需重復從服務器加載。這個無疑試用與圖片的情況。 所有的工作都是按照我們預想的進行;能得到這樣的結果是不錯的。 以后你的網站中就能使用:**.../Res/.....**簡單的一個地址就**OK**了;無論是圖片;附件;css;js;等等都是可行的。而且也沒有暴露你的文件存儲信息, 你敢說不爽?反正我是覺得挺爽的! # END 有到了結束的時候了。 ##### 資源 [WebResource-004_20141205](http://download.csdn.net/detail/qiujuer/8227347) ##### 下一章 針對于下一章,有兩個方向: * 一個是開發一個管理界面 * 還有就是開發針對圖片的Get方法(這個方法能實現圖片的壓縮,分割等功能) 但是沒有想好,大伙想看關于那個的?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看