在Session vs Hidden字段中保留未保存文件的列表

时间:2014-10-14 16:09:00

标签: c# asp.net asp.net-mvc session file-upload

上下文

在我的ASP.Net Mvc项目中,我允许用户上传文件然后出现在网格中。在用户单击保存按钮之前,这些文件不会保存到服务器。但我希望用户能够查看和删除未保存的文件,因此我需要一种方法来保持它们跨越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);
    }

现在,当用户去查看文件时,我可以从Session中读取文件,如下所示

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

隐藏字段解决方案

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

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

问题

即使我不需要在任何其他页面上访问它,或者是否有另一种更适合的解决方案,在这种情况下使用Session是否合理?

2 个答案:

答案 0 :(得分:1)

在用户会话中存储文件实际上并不是一个好主意。想象一下,你有100个用户,每个文件上传5个文件,每个文件是1Mb。您最终将需要存储在内存或SQL Server中的500Mb数据。您应该考虑将文件存储在文件系统中,并且在内存中只存储文件名(路径或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);
     }
 }

因此,每当存储文件时间过期或从缓存中删除文件链接时,它都将从临时目录中删除。

答案 1 :(得分:0)

更确切地说,使用隐藏和会话概念,为什么不使用可以很好的缓存。