35

私はc#MVC2とASP.NETを使用しています。私のフォームの1つには、ファイル入力フィールドが含まれています。このフィールドを使用すると、任意のファイルタイプを選択して、BLOBに変換し、データベースに保存できます。私の問題は、ユーザーがMbの特定の量(約8)を超えるファイルを選択するたびに、次のようなページエラーが発生することです。

The connection was reset
The connection to the server was reset while the page was loading.

ユーザーがアップロードするファイルに8Mbの制限があることを気にしませんが、現在のエラーの発生を停止し、適切な検証メッセージを表示する必要があります(できれば、ModelState.AddModelError関数を使用)。誰か助けてもらえますか?コントローラ内のアップロード機能に到着する前にエラーが発生しているため、ページで他の何かが発生する前にエラーを「キャッチ」することはできません。

4

3 に答える 3

79

1つの可能性は、カスタム検証属性を作成することです。

public class MaxFileSizeAttribute : ValidationAttribute
{
    private readonly int _maxFileSize;
    public MaxFileSizeAttribute(int maxFileSize)
    {
        _maxFileSize = maxFileSize;
    }

    public override bool IsValid(object value)
    {
        var file = value as HttpPostedFileBase;
        if (file == null)
        {
            return false;
        }
        return file.ContentLength <= _maxFileSize;
    }

    public override string FormatErrorMessage(string name)
    {
        return base.FormatErrorMessage(_maxFileSize.ToString());
    }
}

次に、ビューモデルを作成できます。

public class MyViewModel
{
    [Required]
    [MaxFileSize(8 * 1024 * 1024, ErrorMessage = "Maximum allowed file size is {0} bytes")]
    public HttpPostedFileBase File { get; set; }
}

コントローラ:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        if (!ModelState.IsValid)
        {
            // validation failed => redisplay the view
            return View(model);
        }

        // the model is valid => we could process the file here
        var fileName = Path.GetFileName(model.File.FileName);
        var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
        model.File.SaveAs(path);

        return RedirectToAction("Success");
    }
}

とビュー:

@model MyViewModel

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(x => x.File, new { type = "file" })
    @Html.ValidationMessageFor(x => x.File)
    <button type="submit">OK</button>
}

もちろん、これを機能させるには、web.configで許可されているアップロードファイルの最大サイズを十分に大きな値に増やす必要があります。

<!-- 1GB (the value is in KB) -->
<httpRuntime maxRequestLength="1048576" />

およびIIS7の場合:

<system.webServer>
    <security>
        <requestFiltering>
           <!-- 1GB (the value is in Bytes) -->
            <requestLimits maxAllowedContentLength="1073741824" />
        </requestFiltering>
    </security>
</system.webServer>

これで、カスタム検証属性をさらに一歩進めて、クライアント側の検証を有効にして、帯域幅の浪費を回避できます。もちろん、アップロードする前にファイルサイズを確認することは、HTML5FileAPIでのみ可能です。結果として、このAPIをサポートするブラウザのみがこのAPIを利用できます。

したがって、最初のステップは、カスタム検証属性にIClientValidatableインターフェイスを実装させることです。これにより、JavaScriptでカスタムアダプターをアタッチできるようになります。

public class MaxFileSizeAttribute : ValidationAttribute, IClientValidatable
{
    private readonly int _maxFileSize;
    public MaxFileSizeAttribute(int maxFileSize)
    {
        _maxFileSize = maxFileSize;
    }

    public override bool IsValid(object value)
    {
        var file = value as HttpPostedFileBase;
        if (file == null)
        {
            return false;
        }
        return file.ContentLength <= _maxFileSize;
    }

    public override string FormatErrorMessage(string name)
    {
        return base.FormatErrorMessage(_maxFileSize.ToString());
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(_maxFileSize.ToString()),
            ValidationType = "filesize"
        };
        rule.ValidationParameters["maxsize"] = _maxFileSize;
        yield return rule;
    }
}

あとは、カスタムアダプタを設定するだけです。

jQuery.validator.unobtrusive.adapters.add(
    'filesize', [ 'maxsize' ], function (options) {
        options.rules['filesize'] = options.params;
        if (options.message) {
            options.messages['filesize'] = options.message;
        }
    }
);

jQuery.validator.addMethod('filesize', function (value, element, params) {
    if (element.files.length < 1) {
        // No files selected
        return true;
    }

    if (!element.files || !element.files[0].size) {
        // This browser doesn't support the HTML5 API
        return true;
    }

    return element.files[0].size < params.maxsize;
}, '');
于 2012-05-04T09:38:06.117 に答える
1

web.configで特定のURLのリクエストの最大長を増やすことができます。

<location path="fileupload">
  <system.web>
    <httpRuntime executionTimeout="600" maxRequestLength="10485760" />
  </system.web>
</location>
于 2012-05-04T09:46:07.173 に答える
-1

私は少しグーグルで調べて、この問題または例外がGlobal.asaxのアプリケーションのエラーイベントで最もよく処理されることを示唆しているように見える次の2つのURLを思いつきました。

  1. キャッチ'最大リクエスト長を超えました'
  2. 「最大リクエスト長を超えました」例外の処理方法
于 2012-05-04T09:31:21.210 に答える