zoukankan      html  css  js  c++  java
  • 关于缩略图的生成与访问策略的一些经验分享

          之前在一家做图片分享的互联网公司上班,由于一系列的因素公司业务关停,我们不得不另谋出路。不过还是很感谢公司为我们提供了一个相对宽松的工作环境,同时也让我们体会到了一个创业公司的激情与困惑。

          今天就跟大家说说缩略图的那些事儿,以此来做为一个总结和纪念。

          对于项目来说,不管大小一般都或多或少的存在一些图片,有时候我们需要用代码对图片进行一些处理,比如加个水印、生成个缩略图等,这些都是比较普通的需求了。为了让大家对接下来的需求有一个直观的了解,我们还是先来看一些截图

         

                              (1)  照片上传页

     

                             (图2)照片列表页

     

                            (图3)照片单张页

     

          分析代码之前首先介绍一下项目所使用到的一些框架及主要技术点。项目采用MVC3+EF4.1框架搭建,所涉及到的技术主要有GDIIO流、缓存、正则表达式等,下面是项目截图。

    一个很简单的需求,下面我们就来一步步分析如何实现。这里我们讨论的重点不是缩略图本身生成的技术,我们将要讨论的话题主要包括以下几方面:

     

    1.照片信息建模。这是基于EFCode First开发方式的第一步。

    OriginalImage.cs (原始照片信息)

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel.DataAnnotations;
    namespace ImgService.EF.Domain
    {
        public class OriginalImage
        {
            public OriginalImage()
            {
                ThumbnailImage = new List<ThumbnailImage>();
                Created = DateTime.Now;
            }
    
            [Key]
            public string OriginalID { get; set; }
    
            public string Ext { get; set; }
    
            public string Path { get; set; }
    
            public int Width { get; set; }
    
            public int Height { get; set; }
    
            public string Description { get; set; }
    
            public DateTime Created { get; set; }
    
            /// <summary>
            /// 缩略图信息
            /// </summary>
            public virtual List<ThumbnailImage> ThumbnailImage
            {
                get;
                set;
            }
        }
    }

    ThumbnailImage.cs (缩略照片信息)

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    using System.ComponentModel.DataAnnotations;
    
    namespace ImgService.EF.Domain
    {
        public class ThumbnailImage
        {
            public ThumbnailImage()
            {
                Created = DateTime.Now;
            }
    
            [Key]
            public string ID { get; set; }
    
            public string Ext { get; set; }
    
            public string Path { get; set; }
    
            public int Width { get; set; }
    
            public int Height { get; set; }
    
            public string Description { get; set; }
    
            public DateTime Created { get; set; }
    
            [Required]
            public string OriginalID { get; set; }
    
            public virtual OriginalImage OriginalImage { get; set; }
        }
    }

    2.缩略图的基本生成原理。这里不做详细讲解,都是写网上类似的代码,不过应该还有可以优化的地方。

    ImageHelper.cs

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.IO;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Imaging;
    
    namespace ImgService.Helpers
    {
        public class ImageHelper
        {
    
            public static Size GetSize(Stream stream)
            {
                System.Drawing.Image imageObj = System.Drawing.Image.FromStream(stream);
                Size size = imageObj.Size;
                imageObj.Dispose();
                return size;
            }
    
            public static byte[] GetImageBytes(string physicPath)
            {
                if (!File.Exists(physicPath)) { return null; }
    
               FileStream fs = new FileStream(physicPath, FileMode.Open);
               int fileLen = (int)fs.Length;
               byte[] bytes = new byte[fileLen];
               fs.Read(bytes, 0, fileLen);
    
               fs.Close();
               fs.Dispose();
               return bytes;
            }
    
            public static void SaveImage(Bitmap img,string physicPath)
            {
                img.Save(physicPath);
                img.Dispose();
            }
    
            /// <summary>
            /// 计算新尺寸
            /// </summary>
            /// <param name="width">原始宽度</param>
            /// <param name="height">原始高度</param>
            /// <param name="maxWidth">最大新宽度</param>
            /// <param name="maxHeight">最大新高度</param>
            /// <returns></returns>
            private static Size Resize(int width, int height, int maxWidth, int maxHeight)
            {
                decimal MAX_WIDTH = (decimal)maxWidth;
                decimal MAX_HEIGHT = (decimal)maxHeight;
                decimal ASPECT_RATIO = MAX_WIDTH / MAX_HEIGHT;
    
                int newWidth, newHeight;
                decimal originalWidth = (decimal)width;
                decimal originalHeight = (decimal)height;
    
                if (originalWidth > MAX_WIDTH || originalHeight > MAX_HEIGHT)
                {
                    decimal factor;
                    // determine the largest factor 
                    if (originalWidth / originalHeight > ASPECT_RATIO)
                    {
                        factor = originalWidth / MAX_WIDTH;
                        newWidth = Convert.ToInt32(originalWidth / factor);
                        newHeight = Convert.ToInt32(originalHeight / factor);
                    }
                    else
                    {
                        factor = originalHeight / MAX_HEIGHT;
                        newWidth = Convert.ToInt32(originalWidth / factor);
                        newHeight = Convert.ToInt32(originalHeight / factor);
                    }
                }
                else
                {
                    newWidth = width;
                    newHeight = height;
                }
                return new Size(newWidth, newHeight);
            }
    
    
            /// <summary>
            /// 生成宽高相等的缩略图,当原图比例严重失衡时缩略图将只截取原图的一部分
            /// </summary>
            /// <param name="bitmapOriginal"></param>
            /// <param name="newSize"></param>
            /// <returns></returns>
            public static Bitmap Resize(Bitmap bitmapOriginal, int newSize)
            {
                int originalWidth = bitmapOriginal.Width;
                int originalHeight = bitmapOriginal.Height;
    
    
                double standard = Convert.ToDouble(newSize) / Convert.ToDouble(newSize);
                double actualRate = Convert.ToDouble(originalWidth) / Convert.ToDouble(originalHeight);
    
                int imgNewWidth = newSize;
                int imgNewHeight = newSize;
    
                int x = 0;
                int y = 0;
    
                if (actualRate > standard)
                {
                    imgNewWidth = originalWidth * newSize / originalHeight;
                    x = (imgNewWidth - newSize) / 2;
                }
                else
                {
                    imgNewHeight = originalHeight * newSize / originalWidth;
                    y = (imgNewHeight - newSize) / 2;
                }
    
                Bitmap bitmap = new Bitmap(imgNewWidth, imgNewHeight);
                Graphics graphics = Graphics.FromImage(bitmap);
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.Clear(Color.Transparent);
                graphics.DrawImage(bitmapOriginal, new Rectangle(0, 0, imgNewWidth, imgNewHeight));
    
                Bitmap bitmap_cut = new Bitmap(newSize, newSize);
                graphics = Graphics.FromImage(bitmap_cut);
                graphics.DrawImage(bitmap, new System.Drawing.Rectangle(0, 0, newSize, newSize), new System.Drawing.Rectangle(x, y, newSize, newSize), System.Drawing.GraphicsUnit.Pixel);
    
                graphics.Dispose();
                graphics = null;
    
                bitmap.Dispose();
                bitmap = null;
    
                //bitmapOriginal.Dispose();
    
                return bitmap_cut;
            }
    
            /// <summary>
            /// 生成指定宽高的缩略图,当原图比例严重失衡时缩略图将只截取原图的一部分
            /// </summary>
            /// <param name="bitmapOriginal"></param>
            /// <param name="width"></param>
            /// <param name="height"></param>
            /// <returns></returns>
            public static Bitmap Resize(Bitmap bitmapOriginal, int width, int height)
            {
                int originalWidth = bitmapOriginal.Width;
                int originalHeight = bitmapOriginal.Height;
    
    
                double Standard = Convert.ToDouble(width) / Convert.ToDouble(height);
                double ActualRate = Convert.ToDouble(originalWidth) / Convert.ToDouble(originalHeight);
    
                int imgNewWidth = width;
                int imgNewHeight = height;
    
                int x = 0;
                int y = 0;
    
                if (ActualRate > Standard)
                {
                    imgNewWidth = originalWidth * height / originalHeight;
                    x = (imgNewWidth - width) / 2;
                }
                else
                {
                    imgNewHeight = originalHeight * width / originalWidth;
                    y = (imgNewHeight - height) / 2;
                }
    
                Bitmap bitmap = new Bitmap(imgNewWidth, imgNewHeight);
                Graphics graphics = Graphics.FromImage(bitmap);
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.Clear(Color.Transparent);
                graphics.DrawImage(bitmapOriginal, new Rectangle(0, 0, imgNewWidth, imgNewHeight));
    
                Bitmap bitmap_cut = new Bitmap(width, height);
                graphics = Graphics.FromImage(bitmap_cut);
                graphics.DrawImage(bitmap, new System.Drawing.Rectangle(0, 0, width, height), new System.Drawing.Rectangle(x, y, width, height), System.Drawing.GraphicsUnit.Pixel);
    
                graphics.Dispose();
                graphics = null;
                bitmap.Dispose();
                bitmap = null;
                //bitmapOriginal.Dispose();
    
                return bitmap_cut;
            }
            
            /// <summary>
            /// 生成指定宽度的缩略图,高度将等比缩放
            /// </summary>
            /// <param name="bitmapOriginal"></param>
            /// <param name="width"></param>
            /// <returns></returns>
            public static Bitmap ResizeW(Bitmap bitmapOriginal, int width)
            {
                int originalWidth = bitmapOriginal.Width;
                int originalHeight = bitmapOriginal.Height;
    
                int height = 0;
    
                if (originalWidth < width)
                {
                    width = originalWidth;
                    height = originalHeight;
                }
                else
                {
                    height = originalHeight * width / originalWidth;
                }
    
                Bitmap bitmap = new Bitmap(width, height);
                Graphics graphics = Graphics.FromImage(bitmap);
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.Clear(Color.Transparent);
                graphics.DrawImage(bitmapOriginal, new Rectangle(0, 0, width, height));
    
                graphics.Dispose();
                graphics = null;
    
                return bitmap;
            }
    
            /// <summary>
            /// 生成指定高度的缩略图,宽度将等比缩放
            /// </summary>
            /// <param name="bitmapOriginal"></param>
            /// <param name="height"></param>
            /// <returns></returns>
            public static Bitmap ResizeH(Bitmap bitmapOriginal, int height)
            {
                int originalWidth = bitmapOriginal.Width;
                int originalHeight = bitmapOriginal.Height;
    
                int width = 0;
    
                if (originalHeight < height)
                {
                    width = originalWidth;
                    height = originalHeight;
                }
                else
                {
                    width = originalWidth * height / originalHeight;
                }
    
                Bitmap bitmap = new Bitmap(width, height);
                Graphics graphics = Graphics.FromImage(bitmap);
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.Clear(Color.Transparent);
                graphics.DrawImage(bitmapOriginal, new Rectangle(0, 0, width, height));
    
                graphics.Dispose();
                graphics = null;
    
                return bitmap;
            }
    
            /// <summary>
            /// 裁切原图指定区域
            /// </summary>
            /// <param name="bitmapOriginal"></param>
            /// <param name="width"></param>
            /// <param name="height"></param>
            /// <param name="left"></param>
            /// <param name="top"></param>
            /// <returns></returns>
            public static Bitmap Crop(Bitmap bitmapOriginal, int width, int height, int left, int top)
            {
                int originalWidth = bitmapOriginal.Width;
                int originalHeight = bitmapOriginal.Height;
    
                double Standard = Convert.ToDouble(width) / Convert.ToDouble(height);
                double ActualRate = Convert.ToDouble(originalWidth) / Convert.ToDouble(originalHeight);
    
                int imgNewWidth = width;
                int imgNewHeight = height;
    
                int x = 0;
                int y = 0;
    
                if (ActualRate > Standard)
                {
                    imgNewWidth = originalWidth * height / originalHeight;
                    if (left == -1)
                    {
                        x = (imgNewWidth - width) / 2;
                    }
                    else
                    {
                        if (left > (imgNewWidth - width) / 2)
                        {
                            x = (imgNewWidth - width) / 2;
                        }
                        else
                        {
                            x = left;
                        }
                    }
                }
                else
                {
                    imgNewHeight = originalHeight * width / originalWidth;
                    if (top == -1)
                    {
                        y = (imgNewHeight - height) / 2;
                    }
                    else
                    {
                        if (top > (imgNewHeight - height) / 2)
                        {
                            y = (imgNewHeight - height) / 2;
                        }
                        else
                        {
                            y = top;
                        }
                    }
                }
    
                Bitmap bitmap = new Bitmap(imgNewWidth, imgNewHeight);
                Graphics graphics = Graphics.FromImage(bitmap);
    
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.Clear(Color.Transparent);
                graphics.DrawImage(bitmapOriginal, new Rectangle(0, 0, imgNewWidth, imgNewHeight));
    
    
                Bitmap bitmap_cut = new Bitmap(width, height);
                graphics = Graphics.FromImage(bitmap_cut);
                graphics.DrawImage(bitmap, new System.Drawing.Rectangle(0, 0, width, height), new System.Drawing.Rectangle(x, y, width, height), System.Drawing.GraphicsUnit.Pixel);
    
                graphics.Dispose();
                graphics = null;
    
                bitmap.Dispose();
                bitmap = null;
    
    
                //bitmapOriginal.Dispose();
    
                return bitmap_cut;
            }
    
        }
    }

    3.缩略图的存取策略

          原图在上传的同时会生成150 * 150200 * 200800 * X三种不同规格的缩略图文件并存储在项目的Images目录之下,为了提高图片的读取速度,三张缩略图在生成的同时就被放入了缓存当中。这里是把图片放入本地缓存,当然如果实际项目图片较多占用的内存较大,可考虑memcache等第三方分布式缓存策略。以下是核心代码

    ManageController.cs

              //要生成缩略图的保存路径,默认生成800 * x,150 * 150,200 * 200 的三种缩略图
                string w800_ImgName = string.Format("{0}_w_800{1}", upLoadFileInfo.FileID, upLoadFileInfo.FileExt);
                string size150_ImgName = string.Format("{0}_s_150{1}", upLoadFileInfo.FileID, upLoadFileInfo.FileExt);
                string size200_ImgName = string.Format("{0}_s_200{1}", upLoadFileInfo.FileID, upLoadFileInfo.FileExt);
    
                string image800_SavePath = string.Format("~/images/{0}", w800_ImgName);
                string image150_SavePath = string.Format("~/images/{0}", size150_ImgName);
                string image200_SavePath = string.Format("~/images/{0}", size200_ImgName);
    
                string image800_SavePhysicPath = Server.MapPath(image800_SavePath);
                string image150_SavePhysicPath = Server.MapPath(image150_SavePath);
                string image200_SavePhysicPath = Server.MapPath(image200_SavePath);
    
                //生成宽为800的缩略图并保存
                Bitmap bitmap_800 = ImageHelper.ResizeW(new Bitmap(upLoadFileInfo.PostFile.InputStream), 800);
                DB.ThumbnailImages.Add(new ThumbnailImage {
                    OriginalID = upLoadFileInfo.FileID,
                    ID = w800_ImgName,
                    Ext = upLoadFileInfo.FileExt,
                    Path = image800_SavePath,
                    Height = bitmap_800.Height,
                    Width = bitmap_800.Width,
                    Description = Description
                });
                ImageHelper.SaveImage(bitmap_800, image800_SavePhysicPath);
                //将图片存入缓存
                ImageCacheHelper.SetImageCahce(w800_ImgName, ImageHelper.GetImageBytes(image800_SavePhysicPath));
    
    
                //生成宽高为150的缩略图并保存
                Bitmap bitmap_150 = ImageHelper.Resize(new Bitmap(upLoadFileInfo.PostFile.InputStream), 150);
                DB.ThumbnailImages.Add(new ThumbnailImage
                {
                    OriginalID = upLoadFileInfo.FileID,
                    ID = size150_ImgName,
                    Ext = upLoadFileInfo.FileExt,
                    Path = image150_SavePath,
                    Height = bitmap_150.Height,
                    Width = bitmap_150.Width,
                    Description = Description
                });
                ImageHelper.SaveImage(bitmap_150, image150_SavePhysicPath);
                //将图片存入缓存
                ImageCacheHelper.SetImageCahce(size150_ImgName, ImageHelper.GetImageBytes(image150_SavePhysicPath));
                
    
                //生成宽高为200的缩略图并保存
                Bitmap bitmap_200 = ImageHelper.Resize(new Bitmap(upLoadFileInfo.PostFile.InputStream), 200);
                DB.ThumbnailImages.Add(new ThumbnailImage
                {
                    OriginalID = upLoadFileInfo.FileID,
                    ID = size200_ImgName,
                    Ext = upLoadFileInfo.FileExt,
                    Path = image200_SavePath,
                    Height = bitmap_200.Height,
                    Width = bitmap_200.Width,
                    Description = Description
                });
                DB.SaveChanges();
                ImageHelper.SaveImage(bitmap_200, image200_SavePhysicPath);
                //将图片存入缓存
                ImageCacheHelper.SetImageCahce(size200_ImgName, ImageHelper.GetImageBytes(image200_SavePhysicPath));

    4.缩略图访问服务。来看下面几个地址

    http://www.caidian.com/Thumbnail/d92fe65928bc48a8b9ac47d771dad56e_s_200.jpg

    http://www.caidian.com/Thumbnail/d92fe65928bc48a8b9ac47d771dad56e_w_800.jpg

    想必大家都见到过类似的图片地址,其实地址中隐含了图片的生成规则和尺寸。d92fe65928bc48a8b9ac47d771dad56e_s_200.jpg里面的s表示生成规则,200表示要生成的尺寸大小。我这里的实现方式是,当用户访问类似地址的时候其实是访问了ServiceController控制器中名为Thumbnail的Action,而d92fe65928bc48a8b9ac47d771dad56e_s_200.jpg则是传递给Action的参数,这样还有一个好处就是图片访问有了一个统一的处理入口,如果你访问的图片被删除或者地址错误我们可以返回一个默认图片,再也不用担心会出一个红叉了,具体还是来看实现代码。

    ServiceController.cs

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    using ImgService.Helpers;
    using System.Text.RegularExpressions;
    using ImgService.EF;
    using ImgService.EF.Domain;
    using System.Drawing;
    using System.IO;
    
    namespace ImgService.Controllers
    {
        public class ServiceController : Controller
        {
            private ImgServiceContext DB = new ImgServiceContext();
      
            public FileResult Thumbnail(string key = "")
            { 
              //1.从缓存提取图片
              //2.缓存没有,读取缩略图文件
              //3.缩略图不存在,读取图片源文件。生成缩略图,加入缓存
                key = key.ToLower();
                if (string.IsNullOrEmpty(key)) { return null; }
                byte[] bytes = null;
              
                //正则分析Key的内容,可匹配的格式如 43sdfwerw345343ff_s_150.jpg 或 43sdfwerw345343ff_w_800.jpg 等
                string rule = @"(?<p1>([a-z0-9]+)_(s|w)_([\d]+)\.(jpg|png|bmp|tif|tiff))";
    
                Match match = Regex.Match(key, rule, RegexOptions.IgnoreCase);
                if (match.Success)
                {
                    string type = ""; //s或w
                    int imgSize = 200;
                    Bitmap originalBitmap = null;
                    Bitmap thumbnaiBitmap = null;
                    MemoryStream ms = null;
    
                    type = match.Groups[2].Value.Trim().ToLower();
                    int.TryParse(match.Groups[3].Value, out imgSize);
    
                    //确认请求的缩略图是否在系统生成范围之内,验证合法性
                    ThumbnailImage thumbnailData = GetThumbnail(key);
                    if (thumbnailData != null)
                    {
                        //查询缓存
                        bytes = ImageCacheHelper.GetImageCache(key);
                        if (bytes != null && bytes.Length > 0)
                        {
                            return File(bytes, "image/jpeg");
                        }
    
                        //缓存不存在,从文件读取缩略图
                        bytes = ImageHelper.GetImageBytes(Server.MapPath(thumbnailData.Path));
                        if (bytes != null && bytes.Length > 0) //缩略图文件存在
                        {
                            ImageCacheHelper.SetImageCahce(key, bytes);
                            return File(bytes, "image/jpeg");
                        }
                        else  //缩略图不存在,读原图生成缩略图
                        {
                            bytes = ImageHelper.GetImageBytes(Server.MapPath( thumbnailData.OriginalImage.Path ));
                            if (bytes != null && bytes.Length > 0) //原图存在
                            {
                                ms = new MemoryStream(bytes);
                                originalBitmap = new Bitmap(ms);
    
                                if (type == "s")
                                {
                                    thumbnaiBitmap = ImageHelper.Resize(originalBitmap, imgSize);//生成缩略图
                                }
    
                                if (type == "w")
                                {
                                    thumbnaiBitmap = ImageHelper.ResizeW(originalBitmap, imgSize);//生成缩略图
                                }
    
                                thumbnaiBitmap.Save(Server.MapPath(thumbnailData.Path)); //保存缩略图
                                bytes = ImageHelper.GetImageBytes(Server.MapPath(thumbnailData.Path));
                                ImageCacheHelper.SetImageCahce(key, bytes);//把缩略图放入缓存
    
                                ms.Dispose();
                                originalBitmap.Dispose();
                                thumbnaiBitmap.Dispose();
                                return File(bytes, "image/jpeg");
    
                            }
                            else  //原图不存在
                            {
                                return File(Server.MapPath("~/404.jpg"), "image/jpeg");
                            }
                        }
                    }
                    else
                    {
                        return File(Server.MapPath("~/404.jpg"), "image/jpeg");
                    }
                }
                else
                {
                    return File(Server.MapPath("~/404.jpg"), "image/jpeg");
                }
            }
    
            private ThumbnailImage GetThumbnail(string key)
            {
                var q = from t in DB.ThumbnailImages
                        where
                            t.ID == key
                        select t;
                var imgList = q.ToList();
                if (imgList == null || imgList.Count == 0)
                {
                    return null;
                }
                return imgList.First();
            }
        }
    }

    5.自定义路由规则,让缩略图地址更友好

    如果没有自定义路由规则的话,那么缩略图的访问地址应该类似这样。http://www.caidian.com/Thumbnail?key=d92fe65928bc48a8b9ac47d771dad56e_s_200.jpg

    这样的地址给人的第一印象会让人觉着不是一个纯粹的图片地址,所以我对它进行了路由规则的重写,来看看代码

    Global.asax.cs

    public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                //为缩略图的访问配置一个比较友好的地址,访问的地址一般如下
                //http://localhost:1087/Thumbnail/d92fe65928bc48a8b9ac47d771dad56e_s_200.jpg
                //http://localhost:1087/Thumbnail/d92fe65928bc48a8b9ac47d771dad56e_w_800.jpg
                routes.MapRoute(
                    "ImgService", // Route name
                    "thumbnail/{key}", // URL with parameters
                    new { controller = "Service", action = "Thumbnail", key = "" } // Parameter defaults
                );
    
                //照片列表,访问的地址一般如下
                //http://localhost:1087/photos
                routes.MapRoute(
                    "Client-photos", // Route name
                    "photos", // URL with parameters
                    new { controller = "Client", action = "Index"} // Parameter defaults
                );
    
                //单张照片,访问的地址一般如下
                //http://localhost:1087/photo/61e69dc5a92940ad86d9d419c496324d
                routes.MapRoute(
                    "Client-photo", // Route name
                    "photo/{key}", // URL with parameters
                    new { controller = "Client", action = "Photo", key = "" } // Parameter defaults
                );
    
                //这里请注意,默认的路由配置放在自定义配置后面,否则不认自定义路由规则
                routes.MapRoute(
                    "Default", // Route name
                    "{controller}/{action}/{id}", // URL with parameters
                    new { controller = "Manage", action = "Index", id = UrlParameter.Optional } // Parameter defaults
                ); 
            }

    6.关于如何运行程序的注意事项

    下载源码,然后修改web.config中的数据库连接字符串,依你个人的环境而定。

    <connectionStrings>
        <add name="ImgServiceDB" connectionString="server=.;uid=sa;pwd=123456;database=ImgServiceDB" providerName="System.Data.SqlClient"/>
      </connectionStrings>

    接下来就是运行程序了,会自动的跳转到照片上传页面,由于里面没有任何照片数据所以你必须先进行上传,接下来就是看照片了... ...很简单

    当然本项目只是一个很简单的范例程序,真正要开发一套大数据量,高并发的图片分享网站光有这点知识是远远不够的,我在这里也只是算抛砖引玉吧。

    最后,感谢你了浏览到这里,如果你觉得有点收获的话不妨点击推荐。

  • 相关阅读:
    Qt消息机制和事件、事件过滤
    QTableview 获取鼠标坐标的item(QModelIndex)
    qt 拖放dropEvent
    Qt获取控件位置,坐标总结
    Quick Easy FTP Server FTP工具文件传输使用
    Qt QDialog将窗体变为顶层窗体(activateWindow(); 和 raise() )
    makefile 通配符了解% $@ $^ $<
    QLocalServer和QLocalSocket单进程和进程通信
    RC4 加解密
    qt 拷贝文件设置进度条
  • 原文地址:https://www.cnblogs.com/huangzelin/p/2667500.html
Copyright © 2011-2022 走看看