5

私はMVCに比較的慣れていないので、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データベースに簡単なファイルをアップロードする方法について誰かがアドバイスを提供できますか?

4

3 に答える 3

8

何よりもまず、画像をデータベースに保存しないでください。MSSQLでバイト配列または「画像」タイプを使用することを提案する無数の「ガイド」がオンライン上に浮かんでいます。データベースはバイナリデータストレージ用ではありません。確かにバイナリストレージに対応しますが、AR-15で自分の足を撃つことができるからといって、そうすべきだとは限りません。

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

さて、これをすべて処理する最も簡単な方法は、ビューモデルを使用することです。ビューモデルを使用していない場合は、今が開始する絶好の機会です。一般に、実際のデータベースに裏打ちされたモデルをビューに直接送信することは望ましくありません。フォームでは、悪意のあるユーザーによるあらゆる種類の厄介なデータ改ざんの可能性があり、単純なビューでも、通常、必要以上のデータを渡しています。

したがって、最初のステップは、のビューモデルを作成することですProfile。これにProfileViewModelまたはのような名前を付けるのが一般的ProfileVMです。次に、このモデルでProfileは、ビューで編集または操作するプロパティのみを追加します。次に、データベースでバックアップされたモデルにない特別な目的のビュー関数用のプロパティを実際に追加できます。たとえば、SelectListで使用するなどDropDownListFor、そのようなものに頼る代わりに、実際には強い型を維持できますViewBag

画像には、2つのフィールドが必要です。私は通常、次のようなものを使用します。

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

PhotoUpload編集/作成ビューでは、ファイルアップロードフィールドとなるを参照するだけです(ただし、必要Photoに応じて、現在設定されている画像を表示することもできます)。

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

次に、投稿されたファイルをコントローラーアクションで処理するには:

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

アップロードされた画像を保存するホームディレクトリ相対パスはどこuploadPathにあるべきですか。つまり、のようなもの~/uploads/profile/photosです。フォームを投稿する前に必ずディレクトリを作成するか、ロジックを追加してディレクトリの存在を確認し、必要に応じて作成してください(ただし、これにはサーバーに対する信頼性が高い必要があるため、セキュリティが確保されているほとんどの環境では理想的ではありません。大きな懸念)。

次に、ビューモデルからデータベースに裏打ちされたモデルにデータをマッピングする方法が必要です。これは手動で行うことができますが、AutoMapperのようなものを使用すると、作業がはるかに簡単になります。automapperを使用する場合(modelのインスタンスはどこにありますかProfileViewModel):

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タイプを変更します。

于 2013-03-18T20:04:35.760 に答える
2

私が学習していたとき、これこれを使用して、ファイルのアップロードを開始しました。

また、モデルでは、プロパティ Photo を byte[] などにして、データベースに保存し直すことをお勧めします (LINQ to SQL や Entity Framework などを使用していると想定しています)。

上記のリンクに従って、コントローラー メソッドでアップロードを次のように処理することをお勧めします。

  1. コントローラーメソッドに HttpPostedFileBase タイプのパラメーターを持ち、それを「写真」と呼びます(したがって、ファイル入力フィールドが「写真」と呼ばれるビューからバインドされます)
  2. コントローラー メソッドで、パラメーターが null でないことを確認します。そうでない場合は、HttpPostedFileBase の InputStream プロパティを介してファイルを MemoryStream のようなものに読み込むことができます。
  3. MemoryStream から ToArray() メソッドを介して byte[] を取得できます
  4. byte[] をモデルにプラグインし、データベースに保存します

また、完了したら MemoryStream を破棄することを忘れないでください

もっと良い方法があると確信していますが、これらは常に私にとってうまくいきました:-)

HTH、ネイサン

于 2013-03-18T18:58:24.327 に答える
0

私のアプリケーションでは、画像を base64string として保存しているため、nvarchar(max) は使用したデータ型です。これの利点は、JSON オブジェクトで based64String 画像を Web サイトから、または Web サイトに渡すことができることです。

画像を based64string に変換するには

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;

  }
}

次に、このようにメソッドを呼び出すことができます

image.ToBased64String

based64String を画像に変換するには

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

ここで私の答えを参照してください

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

于 2015-05-06T07:38:40.790 に答える