【问题标题】:Why does "Cannot access closed file" error show up? And why only on the server?为什么会出现“无法访问已关闭的文件”错误?为什么只在服务器上?
【发布时间】:2012-07-26 21:12:10
【问题描述】:

我有一个上传图片的代码 sn-p。上传时,它会将文件临时存储在 Session 中。然后单击“保存”,它将文件保存在数据库中。

在我的机器上没有问题,但是在服务器上,每当我尝试上传一些文件,然后单击“保存”时,它都会显示错误“无法访问已关闭的文件”。在谷歌上搜索时,我读到here 这是由于上传了大文件。我想确认一下,是我上传大文件的问题吗?或者它可能是别的东西? 另外,为什么我没有在我的机器上得到这个,而只在服务器上得到这个??

编辑:顺便说一下,file size > 80kb 时出现了错误

上传文件代码:

public ActionResult StoreLogoInSession(HttpPostedFileBase file, int assetID)
        {
            string filename = null;
            if (ValidateOnUpload(file))
            {
                Session.Add("TempLogo", file);
                filename = file.FileName;
                Session.Add("filename", filename);
            }
            return RedirectToAction("Edit", new { id = assetID });
        }

保存代码(这是发生错误的时间):

public ActionResult SaveLogo(LogoModel m, int assetID)
        {
                HttpPostedFileBase file = (HttpPostedFileBase)Session["TempLogo"];
                var logoModel = new LogoModel();
                var asset = this.GenerateAssetForUploadFile(file, (int)m.Asset.AccountID, m.Asset.TextContents, m.Asset.AssetName);
                this.LogoManagementFacade.SaveLogo(asset);
                logoModel.Asset = asset;
                this.LogoModelList.Add(logoModel);
}

【问题讨论】:

  • 使用 Session 不好。使用 Session 存储上传的文件是可憎的。请不要。
  • 好的,但是我现在面临的这个问题呢?
  • 您面临的问题是设计问题。不要将 Session 用于此任务。我的意思是你在工作中使用了错误的工具,现在你在问为什么它不起作用。不知道该告诉你什么。祝你好运解决这个问题。我没办法。我能给你的最好建议是尽快摆脱这个 Session。
  • 好的,这里简要介绍一下场景:有“保存”和“取消”按钮。用户可以选择上传文件,然后取消它(我清除此事件的会话)。在这种情况下,如果我不使用会话,我是否应该在上传时将徽标保存在我的数据库中,并在取消时将其从数据库中删除
  • 会话是有害的,因为它们会将状态引入您的应用程序。默认情况下,它们存储在内存中,这使得它们在网络农场场景中完全无用。它们不能很好地扩展。在 web 农场场景中,您需要考虑一个 off-proc 会话提供程序,使它们完全无用,因为现在您将进行 I/O 调用 => 那么为什么不直接查询相应的数据存储呢?而且,如果您不使用网络场并坚持使用默认的内存提供程序,如您所知,IIS 可以随时回收您的应用程序,从而使您可能存储在 Sessions 中的所有内容无效。

标签: asp.net-mvc-3 file-upload


【解决方案1】:

解决此问题的第一件事是摆脱会话并将上传的文件临时存储在文件系统上,或者如果您在共享文件夹上的网络场中运行,或者如果文件不够大,您可以甚至将它们存储在数据库中。

因此,假设您当前没有在网络场中运行,并且您有一个网络服务器,并且我们可以将上传的文件存储在一个临时文件夹中(当然,您将为此编写一个预定的脚本,该脚本可以运行每个晚上并删除早于 X 天的文件,以避免浪费磁盘空间):

public const string AssetsFolderBase = "~/App_Data";

public ActionResult StoreLogo(HttpPostedFileBase file, int assetID)
{
    string filename = null;
    if (ValidateOnUpload(file))
    {
        var folder = Path.Combine(Server.MapPath(AssetsFolderBase), assetID.ToString());
        if (!Directory.Exists(folder))
        {
            Directory.CreateDirectory(folder);
        }
        folder = Path.Combine(folder, Path.GetFileName(file.FileName));
        file.SaveAs(folder);
    }
    return RedirectToAction("Edit", new { id = assetID });
}

然后当你需要访问它时:

public ActionResult SaveLogo(LogoModel m, int assetID)
{
    var folder = Path.Combine(Server.MapPath(AssetsFolderBase), assetID.ToString());
    var file = Directory.GetFiles(folder).FirstOrDefault();
    if (file == null)
    {
        // no file with this assetID was uploaded => throw an exception
        // or return 404 or something
        return HttpNotFound();
    }

    // at this stage the file variable is pointing to the uploaded filename
    // => you could process it here ...
}

现在,如果您想处理大文件上传,您显然应该确保使用adjust the proper settings in your web.config。默认情况下,您的大小限制为 4MB。

哦,在您编辑 web.config 时,请确保添加以下行,以确保没有其他开发人员犯与您相同的错误并意外使用 ASP.NET 会话:

<sessionState mode="Off" />

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 2023-04-01
    • 2013-01-10
    • 2020-09-06
    • 2021-08-10
    • 2011-04-17
    • 1970-01-01
    相关资源
    最近更新 更多