C# 会话与隐藏字段中未保存文件的持久化列表

C# 会话与隐藏字段中未保存文件的持久化列表,c#,asp.net,asp.net-mvc,session,file-upload,C#,Asp.net,Asp.net Mvc,Session,File Upload,上下文 在我的ASP.NETMVC项目中,我允许用户上传文件,这些文件将显示在网格中。在用户单击“保存”按钮之前,这些文件不会保存到服务器。但是我希望用户能够查看和删除未保存的文件,因此我需要一种方法在ajax调用中持久保存这些文件 会话解决方案 为了实现这一点,我使用Session以一种方式完成了它。当用户上传文件而不是将其保存到服务器时,我将文件字节数组及其文件名存储在一个列表变量中。如下图所示 public class CustomFile { //The real class

上下文

在我的ASP.NETMVC项目中,我允许用户上传文件,这些文件将显示在网格中。在用户单击“保存”按钮之前,这些文件不会保存到服务器。但是我希望用户能够查看和删除未保存的文件,因此我需要一种方法在ajax调用中持久保存这些文件

会话解决方案

为了实现这一点,我使用Session以一种方式完成了它。当用户上传文件而不是将其保存到服务器时,我将文件字节数组及其文件名存储在一个列表变量中。如下图所示

 public class CustomFile 
 {
  //The real class has other properties. Removed for readability
    public byte[] FileBytes { get; set; }
    public string FileName{ get; set; }
    public string ContentType{ get; set; }

  }

 public void FileUploadComplete(CustomFile file)
    {
       List<CustomFile> unsavedFiles = Session["UnsavedFiles"] as List<CustomFile>;

       if(unsavedFiles == null)
           unsavedFiles = new List<CustomFiles>();

       unsavedFiles.Add(file);
    }
公共类自定义文件
{
//实际类具有其他属性。为了可读性而删除
公共字节[]文件字节{get;set;}
公共字符串文件名{get;set;}
公共字符串ContentType{get;set;}
}
public void FileUploadComplete(自定义文件)
{
将未视频文件=会话[“未视频文件”]列为列表;
if(unsavedFiles==null)
unsavedFiles=新列表();
添加(文件);
}
现在,当用户查看文件时,我可以从会话中读取文件,如下所示

 public FileResult LoadFile(string fileName)
    {
        List<CustomFile> unsavedFiles = (List<CustomFile>)Session["UnsavedFiles"];
        CustomFile requestedFile = unsavedFiles.Single(f => f.FileName == fileName);

        return File(requestedFile.FileBytes, requestedFile.ContentType
                  , requestedFile.FileName);
    }
公共文件结果加载文件(字符串文件名)
{
List unsavedFiles=(List)会话[“unsavedFiles”];
CustomFile requestedFile=unsavedFiles.Single(f=>f.FileName==FileName);
返回文件(requestedFile.FileBytes、requestedFile.ContentType
,requestedFile.FileName);
}
隐藏字段解决方案

这很好,但是我不确定在这种情况下使用会话是否合适,因为我只需要访问一页上的未保存文件列表。因此,可以通过将我的“CustomFile”对象列表存储在一个隐藏字段中,然后将其传递给我的操作来持久化信息

这样做的主要问题是,当我将字节数组转换为字符串以存储在隐藏字段中时,我必须找到每个文件使用的正确编码。页面可能会变得非常大,用于存储文件数据

问题


所以,即使我不需要在任何其他页面上访问会话,在这种情况下使用会话是否明智,或者是否有其他更适合的解决方案

与其使用隐藏和会话概念,不如使用缓存,这样会有好处。

在用户会话中存储文件实际上不是一个好主意。假设你有100个用户,他们正在上传5个文件,每个文件都是1Mb。最终,需要将500Mb的数据存储在内存或SQL Server上。您应该考虑将文件存储在文件系统中,并且在内存中,只存储文件名(路径或GUID)。我建议使用临时目录存储上传的文件,并在一段时间后删除它们,以清理磁盘空间。 要清除文件,可以使用
slidingexpiration
参数将指向文件的链接保存到缓存中

 MemoryCache.Default.Add(FileName, FileName, new CacheItemPolicy
                {
                    SlidingExpiration = new TimeSpan(0, 60, 0), // 60 minutes
                    RemovedCallback = RemoveFileFromCacheCallback
                });


 private void RemoveFileFromCacheCallback(CacheEntryRemovedArguments args)
 {
     var fileName = args.CacheItem.Key;
     var fullFileName = Path.Combine(Path.GetTempPath(), fileName);

     if (File.Exists(fullFileName))
     {
         File.Delete(fullFileName);
     }
 }
因此,每当存储文件时间过期或从缓存中删除文件链接时,它都会从临时目录中删除