рдкрд╛рда рдХрд╛ рдЙрджреНрджреЗрд╢реНрдпред Web.config рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕реАрдЦреЗрдВред рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдЕрдиреБрднрд╛рдЧ, рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдФрд░ IConfig рдмрдирд╛ рд░рд╣рд╛ рд╣реИред рдлрд╝рд╛рдЗрд▓реЗрдВ рдЕрдкрд▓реЛрдб рдХрд░рдирд╛ рд╕реАрдЦреЗрдВ, рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓-рдЕрдкрд▓реЛрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдФрд░ рдлрд┐рд░ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░реЗрдВред
рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ, рд╣рдо Web.config рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред рдпрд╣ рдПрдХ xml рдлрд╝рд╛рдЗрд▓ рд╣реИ рдФрд░ рдпрд╣ рдкреНрд░реЛрдЧреНрд░рд╛рдо рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рддрд╛ рд╣реИред
рдЖрдЗрдП рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреНрдпрд╛ рд╣реИ:
- рд╡рд┐рдиреНрдпрд╛рд╕ ред рдпрд╣ рдЦрдВрдб рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдХрдХреНрд╖рд╛рдПрдВ рдЖрдЧреЗ рдШреЛрд╖рд┐рдд рд╡рд░реНрдЧреЛрдВ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░реЗрдВрдЧреАред рд╡рд┐рд╢реЗрд╖рддрд╛ рдирд╛рдо рд╕реЗ рдорд┐рд▓рдХрд░ рдмрдирддрд╛ рд╣реИ - рдпрд╣ рдПрдХ рдЯреИрдЧ рд╣реИ, рдлрд┐рд░ рдШреЛрд╖рд┐рдд рдЕрдиреБрднрд╛рдЧ рдФрд░ рдкреНрд░рдХрд╛рд░ - рдпрд╣ рдХрд┐рд╕ рд╡рд░реНрдЧ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред
- рдХрдиреЗрдХреНрд╢рди рдпрд╣ рдЕрдиреБрднрд╛рдЧ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред
- appSettings ред рдкреНрд░рдХрд╛рд░ рдХреБрдВрдЬреА / рдорд╛рди рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рдЦрдВрдбред
- system.web, system.webServer ред рд╡реЗрдм рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдкреИрд░рд╛рдореАрдЯрд░ рдЕрдиреБрднрд╛рдЧред
- рдХреНрд░рдоред рд░рдирдЯрд╛рдЗрдо рдЯреНрдпреВрдирд┐рдВрдЧ рдЕрдиреБрднрд╛рдЧред рдбреАрдПрд▓ рдХреЗ рдмреАрдЪ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ред
- рд╢реЗрд╖ рдЦрдВрдбред ConfigSection рдореЗрдВ рдШреЛрд╖рд┐рдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдиреНрдп рдЕрдиреБрднрд╛рдЧред
IConfig (рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди)ред
рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рдХреА рддрд░рд╣, рд╣рдо рдПрдХ рд╕реЗрд╡рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╡рд┐рдиреНрдпрд╛рд╕рдХрд░реНрддрд╛ рдмрдирд╛рдПрдВрдЧреЗред рд╡реИрд╢реНрд╡рд┐рдХ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ IConfig рдФрд░ config рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдмрдирд╛рдПрдБ (/Global/Config/IConfig.cs):
public interface IConfig { string Lang { get; } }
рдФрд░
public class Config : IConfig { public string Lang { get { return "ru"; } } }
RegisterServices (/App_Start/NinjectWebCommon.cs) рдкрд░ рдПрдХ рдкрдВрдХреНрддрд┐ рдЬреЛрдбрд╝реЗрдВ:
kernel.Bind<IConfig>().To<Config>().InSingletonScope();
рдФрд░ рдмреЗрд╕рдХрдВрдЯреНрд░реЛрд▓рд░ рдХреЛ рдЖрдЙрдЯрдкреБрдЯ:
[Inject] public IConfig Config { get; set; }
рдЕрдм, рдХрдВрдЯреНрд░реЛрд▓рд░ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдореЗрдВ, рд╣рдо CultureInfo рдХреЛ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдкреБрди: рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВрдЧреЗ (/Controllers/BaseController.cs):
protected override void Initialize(System.Web.Routing.RequestContext requestContext) { try { var cultureInfo = new CultureInfo(Config.Lang); Thread.CurrentThread.CurrentCulture = cultureInfo; Thread.CurrentThread.CurrentUICulture = cultureInfo; } catch (Exception ex) { logger.Error("Culture not found", ex); } base.Initialize(requestContext); }
рдФрд░ Index.cshtml (/Areas/Default/Views/Home/Index.cshtml) рдореЗрдВ рджрд┐рдирд╛рдВрдХ рдЖрдЙрдЯрдкреБрдЯ рдЬреЛрдбрд╝реЗрдВ:
@DateTime.Now.ToString("D")
рд╣рдо рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ:

рдФрд░ рд╕рд╣реА рдорд╛рдпрдиреЗ рдореЗрдВ рдЗрд╕реЗ Web.Config рд╕реЗ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред AppSettings рдореЗрдВ Web.config рдореЗрдВ рд▓рд╛рдЗрди рдЬреЛрдбрд╝реЗрдВ:
<add key="Culture" value="ru" />
Config.cs (/Global/Config/Config.cs) рдореЗрдВ:
public string Lang { get { return ConfigurationManager.AppSettings["Culture"] as string; } }
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ - рдкрд░рд┐рдгрд╛рдо рд╕рдорд╛рди рд╣реИ, рдЕрдм рд╡реЗрдм рдореЗрдВ рдорд╛рди рдХреЛ рдмрджрд▓реЗрдВред fr рдореЗрдВ fr:
<add key="Culture" value="fr" />
рд╣рдореЗрдВ рддрд╛рд░реАрдЦ рдорд┐рд▓рддреА рд╣реИ:
mardi 5 mars 2013
рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛! рдЖрдк рдХрдИ рдФрд░ рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╕реВрдЪреА рдпрд╣рд╛рдВ
http://msdn.microsoft.com/en-us/goglobal/bb896001.aspxрдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╡рд┐рдиреНрдпрд╛рд╕ рдкреНрд░рдХрд╛рд░ рдмрдирд╛рдирд╛
рдЗрд╕ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рдЖрдкрдХрд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рд╡рд┐рдиреНрдпрд╛рд╕ рдмрдирд╛рдХрд░ рджреЗрдЦреЗрдВрдЧреЗред рдЗрд╕ рдЕрдзреНрдпрд╛рдп рдореЗрдВ, рд╣рдо рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдФрд░ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдирд┐рд░реНрдорд╛рдг рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдирд┐рдореНрди рдбреЗрдЯрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдкрд░ рдорд╛рдЗрдо-рдкреНрд░рдХрд╛рд░ рдХреА рдирд┐рд░реНрднрд░рддрд╛, рдФрд░ рдлрд╝рд╛рдЗрд▓ рдЖрдЗрдХрди (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:)
- рд╡рд┐рд╕реНрддрд╛рд░
- рдорд╛рдЗрдо-рдкреНрд░рдХрд╛рд░
- рдмрдбрд╝реЗ рдЖрдЗрдХрди
- рдЫреЛрдЯрд╛ рдЖрдЗрдХрди
рдФрд░ рджреВрд╕рд░реА рдмрд╛рдд, рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛:
- рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рд╢реАрд░реНрд╖рдХ (рдЙрджрд╛ред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрд╡рддрд╛рд░)
- рдЪреМрдбрд╝рд╛рдИ
- рдКрдВрдЪрд╛рдИ
рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдПрдХ рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдХреЗрд╡рд▓ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЛ рд▓рд┐рдЦреВрдВрдЧрд╛ред рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдЖрдЗрдХреЙрдирд╕рд╛рдЗрдЬрд╝ рд╣реЛрдиреЗ рджреЗрдВред рдкрд╣рд▓реА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╡рд░реНрдЧ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП (/Global/Config/IconSize.cs):
public class IconSize : ConfigurationElement { [ConfigurationProperty("name", IsRequired = true, IsKey = true)] public string Name { get { return this["name"] as string; } } [ConfigurationProperty("width", IsRequired = false, DefaultValue = "48")] public int Width { get { return (int)this["width"]; } } [ConfigurationProperty("height", IsRequired = false, DefaultValue = "48")] public int Height { get { return (int)this["height"]; } } }
рдЖрдЗрдП рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
- рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рдирдкреНрд░реЙрдкрд░реНрдЯреА рдореЗрдВ рдирд╛рдо рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдпрд╣ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рд╡рд┐рд╢реЗрд╖рддрд╛ рдирд╛рдо рд╣реИ
- рдЕрдирд┐рд╡рд╛рд░реНрдп - рдЕрдирд┐рд╡рд╛рд░реНрдп рдпрд╛ рдирд╣реАрдВ
- IsKey - рдХреБрдВрдЬреА рд╣реИ (рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдкреНрд░рд╛рдердорд┐рдХ рдХреБрдВрдЬреА рдХреЗ рд░реВрдк рдореЗрдВ)
- DefaultValue - рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди
рдЕрдЧрд▓рд╛ рдХрджрдо рдПрдХ рд╕рдВрдЧреНрд░рд╣ рд╡рд░реНрдЧ рдмрдирд╛рдирд╛ рд╣реИ (рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрдИ рддрддреНрд╡ рд╣реЛрдВрдЧреЗ) рдФрд░ рдПрдХ рдЦрдВрдб (/Global/Config/IconSize.cs):
public class IconSizesConfigSection : ConfigurationSection { [ConfigurationProperty("iconSizes")] public IconSizesCollection IconSizes { get { return this["iconSizes"] as IconSizesCollection; } } } public class IconSizesCollection : ConfigurationElementCollection { protected override ConfigurationElement CreateNewElement() { return new IconSize(); } protected override object GetElementKey(ConfigurationElement element) { return ((IconSize)element).Name; } }
Web.config рдореЗрдВ, рдЬреЛрдбрд╝реЗрдВ:
<iconConfig> <iconSizes> <add name="Avatar173Size" width="173" height="176" /> тАж </iconSizes> </iconConfig>
рдЕрдм рдЖрдкрдХреЛ configSection рдореЗрдВ рдЗрд╕ рдЕрдиреБрднрд╛рдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рд╡рд░реНрдЧ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
<section name="iconConfig" type="LessonProject.Global.Config.IconSizesConfigSection, LessonProject" />
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЯрд╛рдЗрдк рд╡рд┐рд╡рд░рдг рдореЗрдВ рдЖрдкрдХреЛ dll (
LessonProject
) рдХрд╛ рдирд╛рдо рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдореЗрдВ рдпрд╣ рдирд┐рд╣рд┐рдд рд╣реИред рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рд▓реЗрдХрд┐рди рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
MailSettings
рдЪрд▓рд┐рдП smtp-mail рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд┐рдВрдЧрд▓ рдХреЙрдиреНрдлрд┐рдЧрд░ рдмрдирд╛рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:
- SmtpServerред рд╕рд░реНрд╡рд░ рдХрд╛ рдирд╛рдо
- SmtpPortред рдкреЛрд░реНрдЯ, рдЖрдорддреМрд░ рдкрд░ 25 рд╡реЗрдВред
- SmtpUserNameред рд▓реЙрдЧ рдЗрдиред
- SmtpPasswordред рдкрд╛рд╕рд╡рд░реНрдбред
- SmtpReplyред рдЙрддреНрддрд░-рдкрдВрдХреНрддрд┐ рдореЗрдВ рд╡рд╛рдкрд╕реА рдкрддрд╛ред
- SmtpUserред рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рд▓рд╛рдЗрди рдореЗрдВ рд╣реИред
- EnableSslред рд╣рд╛рдБ / рдирд╣реАрдВ, Ssl рдкрд░ рдХрд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред
рдлрд╝рд╛рдЗрд▓ (/Global/Config/MailSetting.cs):
public class MailSetting : ConfigurationSection { [ConfigurationProperty("SmtpServer", IsRequired = true)] public string SmtpServer { get { return this["SmtpServer"] as string; } set { this["SmtpServer"] = value; } } [ConfigurationProperty("SmtpPort", IsRequired = false, DefaultValue="25")] public int SmtpPort { get { return (int)this["SmtpPort"]; } set { this["SmtpPort"] = value; } } [ConfigurationProperty("SmtpUserName", IsRequired = true)] public string SmtpUserName { get { return this["SmtpUserName"] as string; } set { this["SmtpUserName"] = value; } } [ConfigurationProperty("SmtpPassword", IsRequired = true)] public string SmtpPassword { get { return this["SmtpPassword"] as string; } set { this["SmtpPassword"] = value; } } [ConfigurationProperty("SmtpReply", IsRequired = true)] public string SmtpReply { get { return this["SmtpReply"] as string; } set { this["SmtpReply"] = value; } } [ConfigurationProperty("SmtpUser", IsRequired = true)] public string SmtpUser { get { return this["SmtpUser"] as string; } set { this["SmtpUser"] = value; } } [ConfigurationProperty("EnableSsl", IsRequired = false, DefaultValue="false")] public bool EnableSsl { get { return (bool)this["EnableSsl"]; } set { this["EnableSsl"] = value; } } }
Web.config рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ:
<section name="mailConfig" type="LessonProject.Global.Config.MailSetting, LessonProject" />
рдФрд░
<mailConfig SmtpServer="smtp.gmail.com" SmtpPort="587" SmtpUserName="lxndrpetrov" SmtpPassword="**********" SmtpReply="lxndrpetrov@gmail.com" SmtpUser="test" EnableSsl="true" />
рдпрд╣ рд╕рдм рдЕрдм IConfig.cs рдФрд░ config.cs рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ (/Global/Config/IConfig) .cs:
public interface IConfig { string Lang { get; } IQueryable<IconSize> IconSizes { get; } IQueryable<MimeType> MimeTypes { get; } MailSetting MailSetting { get; } }
рдФрд░
public IQueryable<IconSize> IconSizes { get { IconSizesConfigSection configInfo = (IconSizesConfigSection)ConfigurationManager.GetSection("iconConfig"); return configInfo.IconSizes.OfType<IconSize>().AsQueryable<IconSize>(); } } public IQueryable<MimeType> MimeTypes { get { MimeTypesConfigSection configInfo = (MimeTypesConfigSection)ConfigurationManager.GetSection("mimeConfig"); return configInfo.MimeTypes.OfType<MimeType>().AsQueryable<MimeType>(); } } public MailSetting MailSetting { get { return (MailSetting)ConfigurationManager.GetSection("mailConfig"); } }
рд╣рдо MailTemplates - рдЯреЗрдореНрдкрд▓реЗрдЯреНрд╕ рднреА рдЬреЛрдбрд╝реЗрдВрдЧреЗ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдореЗрдВ рдкрдВрдЬреАрдХрд░рдг рдХрд░рддреЗ рд╕рдордп, рдпрд╛ рдкрд╛рд╕рд╡рд░реНрдб рдпрд╛рдж рджрд┐рд▓рд╛рддреЗ рд╕рдордп рдИрдореЗрд▓ рднреЗрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред
рдЖрд╕рд╛рди рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб
рдЕрдм рдПрдХ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рд░реНрд╡рд░ рдкрд░ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рдПрдХ рдорд╛рдирдХ рдЙрджрд╛рд╣рд░рдг рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рдФрд░ рд╣рдо рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдлрд┐рд░ рдХрднреА рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рдмрд╛рддрдЪреАрдд рдХреЗ рд▓рд┐рдП SimpleFileView рд╡рд░реНрдЧ (/Models/Info/SimpleFileView.cs):
public class SimpleFileView { public HttpPostedFileBase UploadedFile { get; set; } }
рдлрд╝рд╛рдЗрд▓реЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд░реНрдЧ рдХреЗ рдирд╛рдо рдкрд░ рдзреНрдпрд╛рди рджреЗрдВред рддреЛ, SimpleFileController рдирд┐рдпрдВрддреНрд░рдХ (/Areas/Default/Controllers/SimpleFileController.cs) рдмрдирд╛рдПрдВ:
public class SimpleFileController : DefaultController { [HttpGet] public ActionResult Index() { return View(new SimpleFileView()); } [HttpPost] public ActionResult Index(SimpleFileView simpleFileView) { return View(simpleFileView); } }
рдФрд░ рджреЗрдЦреЗрдВ:
@model LessonProject.Models.Info.SimpleFileView @{ ViewBag.Title = "Index"; Layout = "~/Areas/Default/Views/Shared/_Layout.cshtml"; } <h2>Index</h2> @using (Html.BeginForm("Index", "SimpleFile", FormMethod.Post, new {enctype = "multipart/form-data", @class = "form-horizontal" })) { <fieldset> <div class="control-group"> <label class="control-label" for="Email"> :</label> <div class="controls"> @Html.TextBox("UploadedFile", Model.UploadedFile, new { type = "file", @class = "input-xlarge" }) @Html.ValidationMessage("UploadedFile") </div> </div> <div class="form-actions"> <button type="submit" class="btn btn-primary"> Upload</button> </div> </fieldset> }
рдкреНрд░рдкрддреНрд░ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рдФрд░ рдкрд╛рда рдмреЙрдХреНрд╕ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдореЗрдВ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдиреЛрдЯ рдХрд░реЗрдВ (рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдкреНрд░рдХрд╛рд░ рдЕрднреА рднреА рдкрд╛рд╕рд╡рд░реНрдб, рдЪреЗрдХрдмреЙрдХреНрд╕, рд░реЗрдбрд┐рдпреЛ рд╣реИ, рд▓реЗрдХрд┐рди @ Html рд╡рд░реНрдЧ рдореЗрдВ рдЙрдирдХреЗ рд▓рд┐рдП рдЗрд╕реА рддрд░реАрдХреЗ рд╣реИрдВ)ред рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдореЗрдВ рд╕реВрдЪрдирд╛рдУрдВ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП Enctype рдХреЛ "рдорд▓реНрдЯреАрдкрд╛рд░реНрдЯ / рдлреЙрд░реНрдо-рдбреЗрдЯрд╛" рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ рдФрд░ рдЬрд╛рдВрдЪреЗрдВред рд╣рдорд╛рд░реА рдлрд╝рд╛рдЗрд▓ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдЕрдкрд▓реЛрдб рдХреА рдЧрдИ рд╣реИ, рдЖрдкрдХреЛ рдмрд╕ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдлрд╝рд╛рдЗрд▓ рдореЗрдВ InputStream рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди рдЪрд▓реЛ рдЗрд╕реЗ рдЕрднреА рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝ рджреЗрдВ рдФрд░ рдХрдорд┐рдпреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
рдкрд╣рд▓рд╛ рджреЛрд╖ рдпрд╣ рд╣реИ рдХрд┐ рд╕рднреА рдмреНрд░рд╛рдЙрдЬрд╝рд░реЛрдВ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдЪрдпрди рдлрд╝реЙрд░реНрдо рдЕрд▓рдЧ рджрд┐рдЦрддрд╛ рд╣реИ:

рдмреЗрд╢рдХ, рдбрд┐рдЬрд╛рдЗрдирд░ рдХрд▓реНрдкрдирд╛ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдлрд╛рдЗрд▓реЗрдВ рд╕рдлрд╛рд░реА рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдЬрд╛рддреА рд╣реИрдВ, рдФрд░ рдЧреНрд░рд╛рд╣рдХ рдХреНрд░реЛрдо рдФрд░ рдЖрдИрдИ рдореЗрдВ рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рд╕реЗ рдкреВрдЫрдирд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ: "рдХрд┐рд╕ рддрд░рд╣ рдХреА рдкрд╣рд▓?"
рджреВрд╕рд░рд╛ рджреЛрд╖ рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдлреЙрд░реНрдо рдиреЗ рд╕рддреНрдпрд╛рдкрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рддреЛ рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЪреБрдирдирд╛ рд╣реЛрдЧрд╛ред рдпрд╛рдиреА рдПрдХ рдРрд╕рд╛ рд░реВрдк рд╣реИ:
- рдкрд╣рд▓рд╛ рдирд╛рдо
- рдЙрдкрдирд╛рдо
- рдИ-рдореЗрд▓
- рдЬрдиреНрдо рдХреА рддрд╛рд░реАрдЦ
- рдлрд╝реЛрдЯреЛ
- рдкрд╛рд╕рдкреЛрд░реНрдЯ рдХреЗ рдкрд╣рд▓реЗ рдкреНрд░рд╕рд╛рд░ рдХреА рддрд╕реНрд╡реАрд░
- рдкрд╛рд╕рдкреЛрд░реНрдЯ рдХреЗ рджреВрд╕рд░реЗ рдкреНрд░рд╕рд╛рд░ рдХреА рддрд╕реНрд╡реАрд░
- рдкрдВрдЬреАрдХрд░рдг рдХреЗ рд╕рд╛рде рдкрд╛рд╕рдкреЛрд░реНрдЯ рдлреЛрдЯреЛ
- рдкрд╛рд╕рд╡рд░реНрдб
- рдлрд┐рд░ рд╕реЗ рдкрд╛рд╕рд╡рд░реНрдб
- рдХреИрдкреНрдЪрд╛
рдФрд░ рдЕрдЪрд╛рдирдХ рдЖрдкрдиреЗ рдкрд╛рд╕рд╡рд░реНрдб рдЧрд▓рдд рд▓рд┐рдЦ рджрд┐рдпрд╛, рдпрд╛ рдЖрдкрдиреЗ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдХреИрдкреНрдЪрд╛ рджрд░реНрдЬ рдХрд┐рдпрд╛, рдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕рдкреЛрд░реНрдЯ рдХреА рджреВрд╕рд░реА рдмрд╛рд░реА рдХреА рдлреЛрдЯреЛ рдмрд╣реБрдд рдмрдбрд╝реА рд╣реИ, рдпрд╛ рдЖрдк рдХрдЪреНрдЪреЗ-рдкреНрд░рд╛рд░реВрдк рд╕реЗ рдЬреЗрдкреАрдИрдЬреА рд╕реЗ рдЖрдЧреЗ рдирд┐рдХрд▓рдирд╛ рднреВрд▓ рдЧрдПред
рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдлреЛрдЯреЛ, рдкрдВрдЬреАрдХрд░рдг рдФрд░ рдХреИрдкреНрдЪрд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рджрд░реНрдЬ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЕрдиреБрдХреВрд▓ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдкрд░реЗрд╢рд╛рди рдХрд░рддрд╛ рд╣реИ (рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдбрд┐рдЬрд╛рдЗрдирд░ рдиреЗ рдЦреВрдмрд╕реВрд░рддреА рд╕реЗ рдЪрд┐рддреНрд░рд┐рдд рдХрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдордирд╣реВрд╕ рд▓рдЧ рд░рд╣рд╛ рд╣реИ)ред
Ajax рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдХрд░реЗрдВ
рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдВ рдХрд┐ рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдХреЛ рдХреИрд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:
- рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ "рдбрд╛рдЙрдирд▓реЛрдб" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИред
- рдлрд╝рд╛рдЗрд▓ рдЪрдпрди рдлрд╝реЙрд░реНрдо рдЦреБрд▓ рдЬрд╛рддрд╛ рд╣реИ
- рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ
- рдлрд╝рд╛рдЗрд▓ рд▓реЛрдб рд╣реЛ рд░рд╣реА рд╣реИ, рдпрд╛ рдпрд╣ рдХрд╣рддреЗ рд╣реБрдП рдПрдХ рддреНрд░реБрдЯрд┐ рдЬрд╛рд░реА рдХреА рдЬрд╛рддреА рд╣реИ рдХрд┐ рдХреБрдЫ рдЧрд▓рдд рд╣реИ
- рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЕрдЧрд░ рдлреЙрд░реНрдо рд╕рддреНрдпрд╛рдкрди рдкрд╛рд╕ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдлрд╝рд╛рдЗрд▓ рд▓реЛрдб рд░рд╣рддреА рд╣реИ рдФрд░ рдЙрд╕реЗ рдлрд┐рд░ рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
рдЗрд╕реЗ рдЕрдЬрд╛рдХреНрд╕ рд▓реЛрдбрд┐рдВрдЧ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдП (
http://fineuploader.com/ ) рдлрд╛рдЗрдирдкрд▓реЛрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рднреБрдЧрддрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рд╕реНрд░реЛрддреЛрдВ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрдХрдЯреНрдард╛ рдХрд░рддреЗ рд╣реИрдВ (рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдмрдВрдбрд▓ рд╣реИ!)ред рд▓рд┐рдВрдХ рдкрд░ рджрд┐рдП рдЧрдП рд╕реНрд░реЛрддреЛрдВ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ:
https://github.com/valums/file-uploader ред Js рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ / Scripts / рдорд╣реАрди-рдЕрдкрд▓реЛрдбрд░ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд▓реЗ рдЬрд╛рдПрдБред рд╣рдо css рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ / рд╕рд╛рдордЧреНрд░реА рдФрд░ рдЫрд╡рд┐рдпреЛрдВ / рд╕рд╛рдордЧреНрд░реА / рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдареАрдХ рд╕реЗ url рдХреЛ рдареАрдХ рд╕реЗ рдкреБрдирдГ рд▓рд┐рдЦрддреЗ рд╣реИрдВред
.qq-upload-spinner { display: inline-block; background: url("images/loading.gif"); width: 15px; height: 15px; vertical-align: text-bottom; } .qq-drop-processing { display: none; } .qq-drop-processing-spinner { display: inline-block; background: url("images/processing.gif"); width: 24px; height: 24px; vertical-align: text-bottom; }
рд╣рдо рдмрдВрдбрд▓рдХреЙрдиреНрдлрд╝рд┐рдЧ.рдХреНрд╕ (/App_Start/BundleConfig.cs) рдореЗрдВ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЖрд░рдВрдн рдХрд░рддреЗ рд╣реИрдВ:
bundles.Add(new ScriptBundle("~/bundles/fineuploader") .Include("~/Scripts/fine-uploader/header.js") .Include("~/Scripts/fine-uploader/util.js") .Include("~/Scripts/fine-uploader/button.js") .Include("~/Scripts/fine-uploader/ajax.requester.js") .Include("~/Scripts/fine-uploader/deletefile.ajax.requester.js") .Include("~/Scripts/fine-uploader/handler.base.js") .Include("~/Scripts/fine-uploader/window.receive.message.js") .Include("~/Scripts/fine-uploader/handler.form.js") .Include("~/Scripts/fine-uploader/handler.xhr.js") .Include("~/Scripts/fine-uploader/uploader.basic.js") .Include("~/Scripts/fine-uploader/dnd.js") .Include("~/Scripts/fine-uploader/uploader.js") .Include("~/Scripts/fine-uploader/jquery-plugin.js") ); bundles.Add(new StyleBundle("~/Content/css/fineuploader") .Include("~/Content/fineuploader.css"));
рдХрдВрдЯреНрд░реЛрд▓рд░ рдмрдирд╛рдПрдБ FileController.cs (/Areas/Default/Controllers/FileController.cs):
public class FileController : DefaultController { [HttpGet] public ActionResult Index() { return View(); } public ActionResult Upload(HttpPostedFileWrapper qqfile) { return Json(new { result = "ok", success = true}); } }
рдХреНрд░рд┐рдпрд╛-рдЕрдкрд▓реЛрдб рд╡рд┐рдзрд┐ qqfile рд╕реНрдЯреНрд░рд┐рдВрдЧ рдорд╛рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреА рд╣реИ, рдореИрдВ рдиреАрдЪреЗ рдЪрд░реНрдЪрд╛ рдХрд░реВрдВрдЧрд╛ рдХрд┐ рдХреНрдпреЛрдВред рдЕрдм рдЗрдВрдбреЗрдХреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рджреГрд╢реНрдп рдмрдирд╛рдПрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:
- рдПрдХ рдмрдЯрди рдмрдирд╛рдПрдБ, рдЬрдм рдХреНрд▓рд┐рдХ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВред
- рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдХреА рдЧрдИ рд╣реИ рдФрд░ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред
- рдлрд╝рд╛рдЗрд▓ рдФрд░ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЧрдпрд╛
- рд╡рд┐рдзрд┐ рдЙрд╕ рд▓рд┐рдВрдХ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреА рд╣реИ рдЬрд╣рд╛рдВ рдлрд╝рд╛рдЗрд▓ рдФрд░ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдХреЛ Json рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛
- рдпрджрд┐ рдлрд╝рд╛рдЗрд▓реЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдирд╣реАрдВ рдХреА рдЬрд╛ рд╕рдХреАрдВ, рддреЛ рдПрдХ рдЙрдкрдпреБрдХреНрдд рддреНрд░реБрдЯрд┐ рдЬрд╛рд░реА рдХреА рдЬрд╛рддреА рд╣реИ
- рд╣рдо json рдкрд░рд┐рдгрд╛рдо рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕реВрдЪрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдлрд╝рд╛рдЗрд▓ рдФрд░ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рд▓реЛрдб рдХрд┐рдП рдЧрдП рд╣реИрдВ
- рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдлреЙрд░реНрдо рд╕рддреНрдпрд╛рдкрди рдФрд░ рд▓реЗрдЦрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд▓рд┐рдП рджреЗрдЦреЗрдВ:
@{ ViewBag.Title = "Index"; Layout = "~/Areas/Default/Views/Shared/_Layout.cshtml"; } @section styles { @Styles.Render("~/Content/css/fineuploader") } @section scripts { @Scripts.Render("~/bundles/fineuploader") @Scripts.Render("~/Scripts/default/file-index.js") } <h2>Index</h2> <fieldset> <div class="control-group"> <label class="control-label" for="Text"> Image </label> <div class="controls"> <div id="UploadImage"> Upload </div> </div> </div> <div> <img src="" alt="" id="ImagePreview" /> </div> </fieldset>
рдЖрдИрдбреА = UploadImage рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░рд╛ рдмрдЯрдиред рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓- index.js рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝реЗрдВ (/ рд╕реНрдХреНрд░рд┐рдкреНрдЯреНрд╕ / рдУрд╡рд░рдлрд╝реЙрд▓реНрдЯ / рдлрд╝рд┐рд▓реЗ-index.js):
function FileIndex() { _this = this; this.ajaxFileUpload = "/File/Upload"; this.init = function () { $('#UploadImage').fineUploader({ request: { endpoint: _this.ajaxFileUpload }, }).on('error', function (event, id, name, reason) {
рдЕрдм рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░реЗрдВ:
public ActionResult Upload(HttpPostedFileWrapper qqfile) { var extension = Path.GetExtension(qqfile.FileName); if (!string.IsNullOrWhiteSpace(extension)) { var mimeType = Config.MimeTypes.FirstOrDefault(p => string.Compare(p.Extension, extension, 0) == 0);
рдлрд╝рд╛рдЗрд▓реЗрдВ рдлрд╝реЛрд▓реНрдбрд░ рдХреЛ рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ - рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдлрд╝реЛрд▓реНрдбрд░ рд╣реЛрдЧрд╛ред рдЖрдЗрдП рдХреЛрдб рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВ:
- рд╣рдо qqfile рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ (рдпрд╣рд╛рдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдмрджрд▓рддреЗ рд╣реИрдВ, рдпрд╣ рдкреИрд░рд╛рдореАрдЯрд░ рдлрд╛рдЗрдиреВрдк рд▓реЛрдбрд░ рдХреЗ рдХрд╛рд░рдг рд╣реИ)ред
- рдЙрд╕рд╕реЗ рд╣рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рдорд┐рд▓рддрд╛ рд╣реИред
- рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╣рдо mimeType рдкрд╛рддреЗ рд╣реИрдВред .Jpg, .gif, .png рдХреЗ рд▓рд┐рдП - рд╣рдореЗрдВ "рдЫрд╡рд┐ / ..." рдкреНрд░рдХрд╛рд░ рдХрд╛ рдорд╛рдЗрдо рдорд┐рд▓рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред
- рдЕрдЧрд▓рд╛, рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо Server.MinPath рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ / Content / files рдлрд╝реЛрд▓реНрдбрд░ (рдЬреЛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рдмрдирд╛рдпрд╛ рдерд╛) рдХреЗ рд▓рд┐рдП рдкреВрд░реНрдг рдкрде рдХреА рд░рдЪрдирд╛ рдХрд░рддреЗ рд╣реИрдВред
- рдЕрдЧрд▓рд╛, SaveAs рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рд╣реЗрдЬреЗрдВред
- Json data.filePath рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рд▓реМрдЯрд╛рдПрдВред
рд╣рдо рдЬрд╛рдВрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╕рдм рдХреБрдЫ рд▓реЛрдб рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдФрд░ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝реЗрдВред
рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдХрд░реЗрдВ
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдордиреЗ рдорд╛рдЗрдо-рдЯрд╛рдЗрдк = "рдЗрдореЗрдЬ \ ..." рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рдзреЛрдЦрд╛ рджрд┐рдпрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЗрдирдореЗрдВ bmp рдФрд░ tiff рдлрд╛рдЗрд▓реЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИрдВред
рддреЛ рдЪрд▓рд┐рдП LessonProject.Tools (PreviewCreator.cs) рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдкреНрд░реАрд╡реНрдпреВ рдХреНрд░рд┐рдПрдЯрд░ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдВ:
public static class PreviewCreator { public static bool SupportMimeType(string mimeType) { switch (mimeType) { case "image/jpg": case "image/jpeg": case "image/png": case "image/gif": return true; } return false; } }
рдФрд░ FileController.cs (/Areas/Default/Controller/FileController.cs) рдореЗрдВ рдмрджрд▓реЗрдВ:
if (mimeType != null && PreviewCreator.SupportMimeType(mimeType.Name))
рдкреНрд░реАрд╡реНрдпреВ рдХреНрд░рд┐рдПрдЯрд░ рдореЗрдВ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдХрд╛рд░реНрдп рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдПрдХ рдЫрд╡рд┐ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рд╕реВрдЪреА рдмрдирд╛рдКрдВрдЧрд╛ рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдПрдХ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реВрдВрдЧрд╛ред рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рд╕рднреА рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдЬреЗрдкреАрдИрдЬреА рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдмрдирд╛рдП рдЧрдП рд╣реИрдВред рддреЛ рдХреНрдпрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ:
- рд░рдВрдЧ рдФрд░ рдХрд╛рд▓реЗ рдФрд░ рд╕рдлреЗрдж рд╡рд┐рдХрд▓реНрдкред рдЧреНрд░реЗрд╕реНрдХреЗрд▓ рдкреИрд░рд╛рдореАрдЯрд░ рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд (рдбрд┐рдлрд╝реЙрд▓реНрдЯ = рдЧрд▓рдд)
- рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрдиред (
CreateAndSavePreview
) рдпрджрд┐ рдореВрд▓ рдЫрд╡рд┐ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдЖрдХрд╛рд░ рд╕реЗ рдЫреЛрдЯреА рд╣реИ, рддреЛ рдЫрд╡рд┐ рдХреЛ рдПрдХ рд╕рдлреЗрдж рдХреИрдирд╡рд╛рд╕ рдХреЗ рдмреАрдЪ рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ рдЖрдХрд╛рд░реЛрдВ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЖрдХрд╛рд░ рдореЗрдВ рдПрдХ рдКрд░реНрдзреНрд╡рд╛рдзрд░ рдЕрднрд┐рд╡рд┐рдиреНрдпрд╛рд╕ (рдкреЛрд░реНрдЯреНрд░реЗрдЯ рдкреНрд░рд╛рд░реВрдк рд╕реЗ рдПрдХ рд╡рд░реНрдЧ) рд╣реИ - рдКрдкрд░реА рднрд╛рдЧ рдХреЛ рдХрд╛рдЯ рджреЗрдВред рдпрджрд┐ рдЕрдиреБрдкрд╛рдд рдЖрдХрд╛рд░ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдХреНрд╖реИрддрд┐рдЬ рд░реВрдк рд╕реЗ рдЙрдиреНрдореБрдЦ рд╣реИ, рддреЛ рдмреАрдЪ рдореЗрдВ рдХрд╛рдЯ рд▓реЗрдВред - рдЕрд╡рддрд╛рд░ред (
CreateAndSaveAvatar
) рдпрджрд┐ рдореВрд▓ рдЫрд╡рд┐ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдЖрдХрд╛рд░ рд╕реЗ рдЫреЛрдЯреА рд╣реИ, рддреЛ рдЫрд╡рд┐ рдмрд╕ рдмрдЪ рдЬрд╛рддреА рд╣реИред рдпрджрд┐ рдЖрдХрд╛рд░реЛрдВ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЖрдХрд╛рд░ рдореЗрдВ рдПрдХ рдКрд░реНрдзреНрд╡рд╛рдзрд░ рдЕрднрд┐рд╡рд┐рдиреНрдпрд╛рд╕ (рдкреЛрд░реНрдЯреНрд░реЗрдЯ рдкреНрд░рд╛рд░реВрдк рд╕реЗ рдПрдХ рд╡рд░реНрдЧ) рд╣реИ - рддреЛ рд╣рдо рдЗрд╕реЗ рдКрдВрдЪрд╛рдИ рдореЗрдВ рдШрдЯрд╛рддреЗ рд╣реИрдВред рдпрджрд┐ рдЕрдиреБрдкрд╛рдд рдЖрдХрд╛рд░ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдХреНрд╖реИрддрд┐рдЬ рд░реВрдк рд╕реЗ рдЙрдиреНрдореБрдЦ рд╣реИ, рддреЛ рдмреАрдЪ рдореЗрдВ рдХрд╛рдЯ рд▓реЗрдВред - рдЫрд╡рд┐ред (
CreateAndSaveImage
) рдпрджрд┐ рдЫрд╡рд┐ рдЕрдзрд┐рдХрддрдо рдЖрдХрд╛рд░ рд╕реЗ рдЫреЛрдЯреА рд╣реИ, рддреЛ рдореВрд▓ рд░рдЦреЗрдВред рдпрджрд┐ рдЫрд╡рд┐ рд╕реАрдорд╛рдУрдВ рдореЗрдВ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рддреЛ рдХрдо рдХрд░реЗрдВ рддрд╛рдХрд┐ рдпрд╣ рдЕрдзрд┐рдХрддрдо рдЖрдХрд╛рд░ рд╕реЗ рдЕрдзрд┐рдХ рди рд╣реЛ, рдФрд░ рд╕рд╣реЗрдЬреЗрдВред - рдЖрдХрд╛рд░ рд╕реЗред (
CreateAndSaveFitToSize
) рдпрджрд┐ рдЫрд╡рд┐ рдЖрдХрд╛рд░ рд╕реЗ рдЫреЛрдЯреА рд╣реИ, рддреЛ рдЗрд╕реЗ рдЖрд╡рд╢реНрдпрдХ рдЖрдХрд╛рд░ рддрдХ рдмрдврд╝рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЧреБрдгрд╡рддреНрддрд╛ рдХреА рдХрдореА рдХреЗ рд╕рд╛рде, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗред - рдХрд╛рдЯ-рдЫрд╛рдВрдЯ рдХрд░реЗрдВред (
CropAndSaveImage
) рдорд╛рдирдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЫрд╡рд┐ рдХреЛ рдХреНрд░реЙрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдкреНрд░реЗрд╖рд┐рдд рд╣реЛрддреЗ рд╣реИрдВред
рдЖрдЗрдП рдПрдХ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдмрдирд╛рдПрдВ (
CreateAndSavePreview
), рдЕрд╡рддрд╛рд░ рд╕реЗ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕реЗ рдЖрдпрд╛рдо рд▓реЗ рд░рд╣реЗ рд╣реИрдВ (/Areas/Default/Controllers/FileController.cs):
var filePreviewPath = Path.Combine("/Content/files/previews", qqfile.FileName); var previewIconSize = Config.IconSizes.FirstOrDefault(c => c.Name == "AvatarSize"); if (previewIconSize != null) { PreviewCreator.CreateAndSavePreview(qqfile.InputStream, new Size(previewIconSize.Width, previewIconSize.Height), Server.MapPath(filePreviewPath)); } return Json(new { success = true, result = "error", data = new { filePath, filePreviewPath } });
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рд▓реЛрдб рд╣реЛ рд░рд╣рд╛ рд╣реИред рдлрд╝рд╛рдЗрд▓реЗрдВ рд▓реЛрдб рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП рдФрд░ рдПрдХ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЕрдм рд╣рдо рдлрд╛рдЗрд▓-рдЗрдВрдбреЗрдХреНрд╕.рдЬреЗрдПрд╕ (/ рд╕реНрдХреНрд░рд┐рдкреНрдЯреНрд╕ / рдбрд┐рдлреЙрд▓реНрдЯ / рдПрдлрд┐рд▓- рдЗрдВрдбреЗрдХреНрд╕.рдПрдХреНрд╕) рдореЗрдВ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХрд░реЗрдВрдЧреЗ:
$('#UploadImage').fineUploader({ request: { endpoint: _this.ajaxFileUpload }, }) .on('error', function (event, id, name, reason) {
рдЕрдм рд╣рдорд╛рд░реА рдлрд╝рд╛рдЗрд▓ рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди рдХреЗ рд╕рд╛рде рднрд░реА рд╣реБрдИ рд╣реИред рдПрдХ рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдкрде рднреА рдЕрд▓рдЧ рд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдЫрд┐рдкреЗ рд╣реБрдП рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдФрд░ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЧрдпрд╛ред
рдЗрд╕ рдбрд┐рдЬрд╛рдЗрди рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдЧрд▓рдд рд╣реИ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджреЛ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ:
- рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЕрдзрд┐рд▓реЗрдЦрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЗрд╕ рддрдереНрдп рд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдХреЗрд╡рд▓ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдЕрд▓рдЧ рд╕реЗ, рдпрд╛ рдереЛрдбрд╝рд╛ рдирдордХ рдЕрд╕рд╛рдЗрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
- рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИред рдпрд╣ рдЗрд╕ рддрдереНрдп рд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд▓рд┐рдП рдлрд╛рдЗрд▓реЗрдВ рдПрдХ рдЕрд▓рдЧ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд▓рд┐рдЦреА рдЬрд╛рддреА рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдПрдХ рдЦреЛрдЬ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЕрдкрд░рд┐рдЪрд┐рдд рд▓реЛрдЧреЛрдВ рдХреЛ рд╣рдЯрд╛рддреЗ рд╣реИрдВред
рд▓рд┐рдВрдХ рджреНрд╡рд╛рд░рд╛ рдлрд╝рд╛рдЗрд▓реЗрдВ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣рд╛ рд╣реИ
рдПрдХ рдФрд░ рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рд╡рд┐рдзрд┐ рд╣реИред рдлрд╝рд╛рдЗрд▓ рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рд▓рдЯрдХреА рд╣реБрдИ рд╣реИ, рдФрд░ рд╣рдо рдЗрд╕реЗ рдкрде рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрдм рдлреЗрд╕рдмреБрдХ рдореЗрдВ рд▓реЙрдЧ рдЗрди рдХрд░рддреЗ рд╣реИрдВ), рдФрд░ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓рд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВред
рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
var webClient = new WebClient(); var bytes = webClient.DownloadData(url); var ms = new MemoryStream(bytes);
рдЬрд╣рд╛рдБ url рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдкрде рд╣реИред рдпрд╣ HttpWebRequest рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ:
public ActionResult Export(string uri) { HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri); webRequest.Method = "GET"; webRequest.KeepAlive = false; webRequest.PreAuthenticate = false; webRequest.Timeout = 1000; var response = webRequest.GetResponse(); var stream = response.GetResponseStream(); var previewIconSize = Config.IconSizes.FirstOrDefault(c => c.Name == "AvatarSize"); var filePreviewPath = Path.Combine("/Content/files/previews", Guid.NewGuid().ToString("N") + ".jpg"); if (previewIconSize != null) { PreviewCreator.CreateAndSavePreview(stream, new Size(previewIconSize.Width, previewIconSize.Height), Server.MapPath(filePreviewPath)); } return Content("OK"); }
рдпрд╣рд╛рдБ рдлрд╝рд╛рдЗрд▓ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╣рдо рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВ:
http://localhost/File/Export?uri=https://st.free-lance.ru/users/chernikov/upload/sm_f_81850beffd0d0c89.jpg
рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдФрд░ рд╕рдВрд╕рд╛рдзрд┐рдд рдХреА рдЧрдИ рдереАред рд╕рдм рдХреБрдЫ рд╕реБрдкрд░ рд╣реИ!
рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ рдкреНрд░реАрд╡реНрдпреВрдХреНрд░реАрдЯ рдбрд┐рдмрдЧрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рдХрд┐ рд╡рд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╕рднреА рд╕реНрд░реЛрдд
https://bitbucket.org/chernikov/lessons рдкрд░ рд╕реНрдерд┐рдд рд╣реИрдВ