2013-03-18 1 views
5

私はMVCには比較的新しいので、SQL Serverデータベースにファイル(特にイメージ)をアップロードする必要はありませんでした。正直言って、私はここで何をやっているのか分かりません。MVC4では、ドメインモデルの一部であるSQL Serverにファイル(画像)をアップロードするにはどうすればよいですか?

は、ここで私がこれまで持っているものだ - ここに私のドメインモデルは、(私のモデルでHttpPostedFileBaseに注意してください - これは私がアップロードしたいものです)です:

public class Profile 
{ 
    [Key] 
    public int Id { get; set; } 

    [Required(ErrorMessage="Years of service is required")] 
    [DisplayName("Years Service:")] 
    public int YearsService { get; set; } 

    [DataType(DataType.MultilineText)] 
    [DisplayName("Notable Achivements:")] 
    public string NotableAchivements { get; set; } 

    [Required(ErrorMessage = "Technical skills are required")] 
    [DataType(DataType.MultilineText)] 
    [DisplayName("Technical Skills:")] 
    public string TechnicalSkills { get; set; } 

    [DisplayName("Upload Image: ")] 
    public HttpPostedFileBase Photo { get; set; } 

    public string CreatedBy { get; set; } 
    public DateTime CreatedDate { get; set; } 
    public string ModifiedBy { get; set; } 
    public DateTime ModifiedDate { get; set; } 
} 

そしてここでは、私の見解です:

@using (Html.BeginForm("Create", "Profiles", FormMethod.Post, new { enctype = "multipart/form-data" })) 
{ 
<div class="editor-label"> 
    @Html.LabelFor(model => model.YearsService) 
</div> 
<div class="editor-field"> 
    @Html.EditorFor(model => model.YearsService) 
    @Html.ValidationMessageFor(model => model.YearsService) 
</div> 

<div class="editor-label"> 
    @Html.LabelFor(model => model.NotableAchivements) 
</div> 
<div class="editor-field"> 
    @Html.EditorFor(model => model.NotableAchivements) 
    @Html.ValidationMessageFor(model => model.NotableAchivements) 
</div> 

<div class="editor-label"> 
    @Html.LabelFor(model => model.TechnicalSkills) 
</div> 
<div class="editor-field"> 
    @Html.EditorFor(model => model.TechnicalSkills) 
    @Html.ValidationMessageFor(model => model.TechnicalSkills) 
</div> 

<input type="file" name="photo" /> 
<input type="submit" name="Submit" id="Submit" value="Upload" /> 
} 

私が間違っていることが明らかに明白な何かがあることを願っています。 SQL Serverデータベースへの単純なファイルアップロードの方法に関するアドバイスを誰でも提供できますか?

答えて

8

まず ネイサン、

HTH :-)私のために働いた何よりも、自分のデータベースに画像を保存しないでください。オンラインで膨大な数の "ガイド"が浮かび上がっているので、MSSQLでバイト配列や "イメージ"タイプを使用することをお勧めします。データベースはバイナリデータストレージ用ではありません。彼らはバイナリストレージに対応しますが、確かにがAR-15の足で自分を撃つことができるので、になります。

代わりに、イメージが所属する場所、つまりファイルシステムを保存します。そして、データベース内のパスを参照するだけです。

これをすべて処理する最も簡単な方法は、ビューモデルです。ビューモデルを使用していない場合は、既に始めるのがいいでしょう。一般的に、データベースバックアップされた実際のモデルを直接ビューに送信する必要はありません。フォームでは、悪意のあるユーザーによるあらゆる種類の厄介なデータ改ざんの可能性があります。単純なビューであっても、通常は必要以上のデータを渡しています。

したがって、最初の手順はProfileのビューモデルを作成することです。これは一般的にProfileViewModelまたはProfileVMのような名前です。次に、このモデルでは、編集したり他の方法でやり取りしたりするプロパティーをProfileに追加します。次に、SelectListDropDownListForと一緒に使用するなど、特殊目的のビュー機能のデータベースバックアップモデルにではないというプロパティを実際に追加することができるので、実際にはViewBagそのようなもの。

画像には2つのフィールドが必要です。私は通常、次のようなもので行く:

public string Photo { get; set; } 
public HttpPostedFileBase PhotoUpload { get; set; } 

あなたの編集では/ビューを作成するには、現在設定されている画像を表示するPhotoを使用することができますが、あなただけ(あなたのファイルアップロードフィールドされる、PhotoUploadを参照します、同様に、あなたが好きなら)。

その後
@Html.TextBoxFor(m => m.PhotoUpload, new { type = "file" }) 

、お使いのコントローラのアクションで掲示されるファイルを処理するために:uploadPathはホームディレクトリの相対パスアップロードした画像を保存するべきである

if (model.PhotoUpload.ContentLength > 0) { 
    // A file was uploaded 
    var fileName = Path.GetFileName(model.PhotoUpload.FileName); 
    var path = Path.Combine(Server.MapPath(uploadPath), fileName); 
    model.PhotoUpload.SaveAs(path); 
    model.Photo = uploadPath + fileName; 
} 

、すなわち~/uploads/profile/photosようなものを。フォームを投稿しようとする前にディレクトリを作成するか、ディレクトリの存在を確認するロジックを追加し、必要に応じて作成してください(これはサーバーの信頼性を高める必要があります。大きな懸念)。

次に、ビューモデルのデータをデータベースバックアップモデルにマップする方法が必要です。これを手動で行うことはできますが、AutoMapperのようなものを使用すると、人生がずっと楽になります。 (modelProfileViewModelのインスタンスである)automapperで:プロファイルのようなものであるため、

var profile = AutoMapper.Mapper.Map<Profile>(model); 

それとも、それはあなたが新しいものを作成するよりも、既存のモデルを編集することがありますことを、より一般的です:

var profile = db.Profiles.Find(userId); 
... 
Automapper.Mapper.Map(model, profile); 

実際のモデルでは、PhotoUploadプロパティはありません。ちょうどPhotoです。ビューモデルでPhotoに設定したパスは、同じ名前のモデルのプロパティにマップされるため、更新されたプロファイルを保存するだけです。

また、写真をアップロードすることについて話しているので、ユーザーがWord文書のような愚かなものではなく画像をアップロードしていることを確認するためにコンテンツタイプのチェックを追加することをお勧めします。あなたのif (ModelState.IsValid)チェックする前に、追加します。

var validTypes = new[] { "image/jpeg", "image/pjpeg", "image/png", "image/gif" }; 
if (!validTypes.Contains(model.PhotoUpload.ContentType)) 
{ 
    ModelState.AddModelError("PhotoUpload", "Please upload either a JPG, GIF, or PNG image."); 
} 

の変更など必要なMIMEタイプは、あなたのビジネスケースを一致させます。

+1

どのようにこの状況でWebファームを処理しますか? –

+0

イメージをデータベースに保存する正当な理由があります。この場合、ファイルシステムへの保存はどのように機能しますか? –

+1

特にマルチテナント環境では、静的リソースサーバー、またはおそらくはオフサイトCDNが必要です。したがって、あなたのサイトはすべて、 'static.yourdomain.com'のようなものを参照するだけです。これは大男(Facebook、Twitter、Googleなど)が行うことです。データベースに格納するには、そのデータベースから読み込み、ASP.NETスタック全体を回転させ、画像データをレスポンスに書き込む必要があります。小規模なサイトではそれほど悪くないかもしれませんが、GoogleやFacebookなどのサイトを運営しようとしているかもしれません。あなたは絶えず倒れているか、何百万人ものインフラストラクチャに投資しています。 –

2

私が学んだとき、私はthisthisを使ってファイルのアップロードを開始しました。

また、あなたのモデルでは、写真のプロパティをbyte []または類似のものにして、データベースに保存し直す必要があることをお勧めします(LINQ to SQLまたはEntity Frameworkのようなものを使用していると仮定しています)。お使いのコントローラメソッドで型のパラメータを持つ

  1. HttpPostedFileBase、それはあなたからバインドしますので、「写真」(それを呼び出す:

    上記のリンクに続いて、私がして、コントローラのメソッドでアップロードを処理することをお勧めあなたのコントローラメソッドでは、パラメータがnullではないことを確認し、そうでなければ、HttpPostedFileBaseのInputStreamプロパティを介してMemoryStreamのようなものにファイルを読み込むことができます。

  2. MemoryStreamからToArray()メソッドを使用してバイト[]を取得できます
  3. あなたのモデルにバイト[]を接続してから、

また、あなたのデータベースに保存し、私はより良い方法があると確信しているが、これらは常に持っている

をやったときのMemoryStreamを処分することを忘れないでください

0

私のアプリケーションでは、私はbase64stringとしてイメージをソートしました。したがって、nvarchar(max)は私が使用したデータ型です。これのアドバンテージは、JSONオブジェクトのbased64StringイメージをWebサイトとの間で渡すことができるということです。そして、あなたがここに私の答えを

を参照してください画像

public static ImageFromBased64String(string based64Image, string path) 
{ 
    Image image = null; 
    var bytes = Convert.FromBased64String(based64String); 
    using (var fileStream = new FileStream(path, FileMode.Create)) 
    { 
    fileStream.Write(bytes, 0, bytes.Length); 
    fileStream.Flush(); 
    image = Image.FromStream(fileStream, true); 
    return image; 
    } 
} 

にbased64Stringを変換するには、この

image.ToBased64String 

のようなあなたのメソッドを呼び出すことができます

public static string ToBased64String(this Image image, ImageFormat format) 
{ 
    using (MemoryStream ms = new MemoryStream()) 
    { 
    image.Save(ms, format); 
    byte[] imageBytes = ms.ToArray(); 
    string based64String = Convert.ToBased64String(imageBytes); 
    return based64String; 

    } 
} 

をbased64stringに画像を変換するには

https://stackoverflow.com/a/30057680/1554116

関連する問題