C# 会话与隐藏字段中未保存文件的持久化列表
上下文 在我的ASP.NETMVC项目中,我允许用户上传文件,这些文件将显示在网格中。在用户单击“保存”按钮之前,这些文件不会保存到服务器。但是我希望用户能够查看和删除未保存的文件,因此我需要一种方法在ajax调用中持久保存这些文件 会话解决方案 为了实现这一点,我使用Session以一种方式完成了它。当用户上传文件而不是将其保存到服务器时,我将文件字节数组及其文件名存储在一个列表变量中。如下图所示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
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);
}
}
因此,每当存储文件时间过期或从缓存中删除文件链接时,它都会从临时目录中删除