ASP.NET MVCレッスン9.構成とファイルのアップロード

レッスンの目的。 Web.config構成ファイルの使用方法を学習します。 独自のConfigSectionおよびIConfigを作成するアプリケーションセクション。 ファイルのアップロード、ファイルアップローダーを使用したファイルのダウンロード、およびファイルの処理を学びます。



このチュートリアルでは、Web.config構成ファイルでの作業を見ていきます。 これはxmlファイルであり、プログラム設定を保存します。



このファイルが何で構成されているかをさらに詳しく考えてみましょう。









IConfig(および実装)。


リポジトリのように、コンフィギュレーターをサービスとして作成します。 グローバルフォルダー(/Global/Config/IConfig.cs)にIConfigおよびConfig実装を作成します。

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();
      
      





BaseControllerへの出力:

 [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; } }
      
      





開始-結果は同じですが、今度はWeb.configの値をfrに変更します。

 <add key="Culture" value="fr" />
      
      





日付を取得します。

 mardi 5 mars 2013
      
      







いいね! さらにいくつかの言語で試すことができます。 略語のリストはこちらhttp://msdn.microsoft.com/en-us/goglobal/bb896001.aspx



独自のConfigSectionタイプを作成する


このパートでは、独自のConfigSectionの作成について説明します。 この章では、ファイルのアップロードとプレビューの作成を実装します。 次のデータが必要です。まず、拡張子に対するMIMEタイプの依存関係、およびファイルアイコン(ダウンロードなど):





次に、プレビューを作成するためのデータ:





どちらのタイプも同じ方法で実行されるため、どちらか一方の作成のみを記述します。 プレビューを作成するには、IconSizeにします。 最初に行うことは、ConfigurationElement(/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"]; } } }
      
      







さらに詳しく考えてみましょう。





次のステップでは、コレクションクラス(多くの要素があるため)とセクション(/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



)の名前を指定する必要があることに注意してください。 これは重要ですが、単体テストでカバーされます。



メール設定


smtp-mailを操作するための設定用の単一の構成を作成しましょう。 必要なもの:





ファイル(/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> }
      
      







フォーム属性のenctypeとTextBox属性の型に注意してください(実際、型はまだパスワード、チェックボックス、ラジオですが、@ Htmlクラスには対応するメソッドがあります)。 大量の情報をロードするには、Enctypeを「multipart / form-data」に設定する必要があります。



ダウンロードして確認してください。 ファイルは安全にアップロードされます。InputStreamを特定のファイルに保存するだけです。 しかし、今のところは残して、欠点を考慮しましょう。



最初の欠点は、すべてのブラウザでファイル選択フォームが異なって見えることです:







もちろん、デザイナーはファイルがSafariでダウンロードされ、顧客がChromeとIEで確認し、開発者に「どのようなイニシアチブか」と尋ね始めます。

2番目の欠点は、フォームが検証に合格しなかった場合、これらのフィールドを再度選択する必要があることです。 つまり そのような形式があります:





そして、突然パスワードを間違って入力したか、キャプチャを間違って入力したか、パスポートの2番目のターンの写真が大きすぎるか、rawフォーマットからjpegに追い越すのを忘れました。



そのため、写真、登録、キャプチャを再入力する必要があります。 当然、これはユーザーフレンドリーではなく、顧客を困らせます(さらに、デザイナーは美しく塗装されていますが、惨めに見えます)。



Ajaxを使用してファイルをアップロードする


ファイルのアップロードの動作を決定します。





これはajaxロードと呼ばれ、fineuploaderを使用します( http://fineuploader.com/ )。 ライブラリは有料ですが、ソースをダウンロードして収集します(バンドルがあります!)。 リンク( https://github.com/valums/file-uploader)でソースをダウンロードします 。 jsファイルを/ Scripts / fine-uploaderフォルダーに移動します。 cssファイルを/ Contentに、画像を/ Content / imagesに移動します。 画像のfineuploader.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; }
      
      







BundleConfig.cs(/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}); } }
      
      





action-uploadメソッドはqqfile文字列値を受け入れます。その理由を以下で説明します。 次に、インデックスのビューを作成します。 これを行うには:





インデックスの表示:

 @{ 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>
      
      







id = UploadImageのボタン。 処理するfile-index.jsファイルを追加します(/Scripts/default/file-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) { //do something }) .on('complete', function (event, id, name, responseJSON) { alert(responseJSON); }); } } var fileIndex = null; $().ready(function () { fileIndex = new FileIndex(); fileIndex.init(); });
      
      







ダウンロードを処理します。

 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); //  if (mimeType.Name.Contains("image")) { //    var filePath = Path.Combine("/Content/files", qqfile.FileName); qqfile.SaveAs(Server.MapPath(filePath)); return Json(new { success = true, result = "error", data = new { filePath } }); } } return Json(new { error = "  ", success = false }); }
      
      







ファイルフォルダーをコンテンツに追加します-これがユーザーデータフォルダーになります。 コードを分析しましょう:





すべてがロードされているかどうかを確認し、プレビューの作成に進みます。



プレビュー作成


まず、mime-type = "image \ ..."を少しごまかしました。これらには、ブラウザでサポートされていないbmpおよびtiffファイルが含まれているためです。

だから、LessonProject.Tools(PreviewCreator.cs)プロジェクトでPreviewCreatorクラスを作成しましょう。

  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))
      
      







PreviewCreatorにはプレビューを作成するための多くの機能があるため、画像を作成するためのさまざまなオプションをリストし、そのうちの1つを詳細に分析します。 すべてのプレビューがjpeg形式で作成されることを考慮する価値があります。 それで、オプションは何ですか:





プレビューを作成して( CreateAndSavePreview



)、構成から寸法を取得してAvatarSizeプレビュー(/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 } });
      
      







始めます。 ダウンロード。 ファイルをロードする必要があり、プレビューが作成されます。

ここで、file-index.js(/Scripts/default/file-index.js)で処理を行います。

 $('#UploadImage').fineUploader({ request: { endpoint: _this.ajaxFileUpload }, }) .on('error', function (event, id, name, reason) { //do something }) .on('complete', function (event, id, name, responseJSON) { $("#ImagePreview").attr("src", responseJSON.data.filePreviewPath); });
      
      







これで、ファイルがプレビューとともにロードされます。 また、大きなファイルのパスを個別に転送し、たとえば非表示フィールドに記録して、将来データベースに文字列として保存することもできます。

この設計で間違っているのは、次の2つの問題です。





リンクによるファイルの取得


別のファイルアップロード方法があります。 ファイルはインターネット上で自由にハングアップし、そのパスを指定し(たとえば、facebookでログインする場合)、リンクを使用してこのファイルを既に保存します。

これは次のように行われます。

 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"); }
      
      







ここで、ファイルはGuid.NewGuidの生成を通じて設定されます。 私たちはチェックします:

 http://localhost/File/Export?uri=https://st.free-lance.ru/users/chernikov/upload/sm_f_81850beffd0d0c89.jpg
      
      





ファイルがアップロードされ、処理されました。 すべてが最高です!



PreviewCreatorデバッガーを使用して、そこですべてがどのように機能するかを理解することをお勧めします。



すべてのソースはhttps://bitbucket.org/chernikov/lessonsにあります



All Articles