无法将 HttpPostedFileBase 保存到会话变量并使用两次
Posted
技术标签:
【中文标题】无法将 HttpPostedFileBase 保存到会话变量并使用两次【英文标题】:cannot save HttpPostedFileBase to session variable and use twice 【发布时间】:2011-06-12 11:32:36 【问题描述】:早上好- 我正在尝试将 HttpPostedFileBase(它始终是一个简单的 CSV 文件)保存到一个会话变量中,如下所示:
[HttpPost]
public ActionResult Index(HttpPostedFileBase importFile)
Session.Remove("NoteImport");
var noteImport = new NoteImport ImportFile = importFile, HeaderList = NoteService.HeaderList(importFile) ;
Session["NoteImport"] = noteImport;
return RedirectToAction("FileNote");
如您所见,我将 importFile 转储到我的 NoteImport 类中。目前,ImportFile 属性是可公开访问的 HttpPostedFileBase 类型。
我第一次在我的服务中使用这个属性(创建标头值列表的方法),我没有问题:
public List<string> HeaderList(HttpPostedFileBase fileStream)
var sr = new StreamReader(fileStream.InputStream);
var headerString = sr.ReadLine();
var headerArray = headerString.Split(',');
var headerList = new List<string>();
foreach (var header in headerArray)
if (!ValidateHeader(header))
throw new InvalidDataException("Invalid header name: " + header);
headerList.Add(header);
return headerList;
以上工作正常,并且暂时返回了我需要的内容。
我的问题在于下面的代码。当我调用 ReadLine() 时,它不会从 HttpPostedFileBase 中得到任何东西。
public List<string> ImportFileStream(HttpPostedFileBase importFile)
var sr = new StreamReader(importFile.InputStream);
var headerString = sr.ReadLine();
var headerArray = headerString.Split(',');
var cb = new DelimitedClassBuilder("temp", ",") IgnoreFirstLines = 0, IgnoreEmptyLines = true, Delimiter = "," ;
foreach (var header in headerArray)
cb.AddField(header, typeof(string));
cb.LastField.FieldQuoted = true;
cb.LastField.QuoteChar = '"';
var engine = new FileHelperEngine(cb.CreateRecordClass());
var dataTable = engine.ReadStreamAsDT(sr);
var noteData = new List<string>();
var jsonSerializer = new JsonSerializeDataRow();
foreach (var row in dataTable.Rows)
var dataRow = row as DataRow;
var jsonRow = jsonSerializer.Serialize(dataRow);
noteData.Add(jsonRow);
return noteData;
我已尝试关闭 HttpPostedFileBase;我还将流位置设置为 0。似乎没有任何进展。我有一种感觉,我需要在保存到会话之前将其更改为不同的类型。
有什么建议吗??
谢谢!
【问题讨论】:
【参考方案1】:HttpPostedFile
直接从 HTTP 请求流中读取。
不适合重复使用。
【讨论】:
【参考方案2】:您不能将HttpPostedFileBase
存储到会话中。这没有任何意义。它包含一个指向来自 HTTP 请求流的文件内容的流,该流在请求结束时被垃圾收集。在存储到会话之前,您需要将其序列化为一些自定义对象。例如:
public class MyFile
public string Name get; set;
public string ContentType get; set;
public byte[] Contents get; set;
现在继续并将其存储到会话中。当然,您应该知道,这样做会将整个文件内容存储到内存中,这可能不是您想要做的事情,尤其是在上传的文件可能很大的情况下。另一种可能性是将文件内容存储到磁盘或数据库等可持久媒体中,并仅将指向该媒体的指针存储到会话中,以便您以后可以检索它。
【讨论】:
完美 - 谢谢!这个功能最多每天使用一次(目前,我们可能每隔一周使用一次,我们用来手动完成此操作的最大 CSV 文件是 55K。我认为由于最小使用,存储在会话中会比写入临时文件更有效。你同意吗? @BueKoW,是的,文件大小似乎可以存储到会话中。 你能分享一下如何做到这一点吗?谢谢【参考方案3】:如果你使用 HttpPostedFileBase 你需要先克隆它, 我使用了 git 中的代码 你只需要将它作为一个类添加到你的命名空间中:
public static class HttpPostedFileBaseExtensions
public static Byte[] ToByteArray(this HttpPostedFileBase value)
if (value == null)
return null;
var array = new Byte[value.ContentLength];
value.InputStream.Position = 0;
value.InputStream.Read(array, 0, value.ContentLength);
return array;
现在您可以像这样读取 HttpPostedFileBase:
private static void doSomeStuff(HttpPostedFileBase file)
try
using (var reader = new MemoryStream(file.ToByteArray()))
// do some stuff... say read it to xml
using (var xmlTextReader = new XmlTextReader(reader))
catch (Exception ex)
throw ex;
使用后你仍然可以在你的主代码中编写:
file.SaveAs(path);
它会将其保存到文件中。
【讨论】:
以上是关于无法将 HttpPostedFileBase 保存到会话变量并使用两次的主要内容,如果未能解决你的问题,请参考以下文章
ASP.Net MVC - 从 HttpPostedFileBase 读取文件而不保存
Asp.Net MVC 在 Edit Get 中编辑上传的图片(HTTPPostedFileBase)
将 HttpPostedFileBase 转换为 byte[]