无法将HttpPostedFileBase保存到会话变量并使用两次

时间:2011-01-20 13:43:23

标签: c# asp.net-mvc-2 inputstream httppostedfilebase

早上好 - 我试图将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.似乎没有任何进展。我有一种感觉,我需要在保存到会话之前将其更改为其他类型。

有什么建议吗?

谢谢!

3 个答案:

答案 0 :(得分:5)

您无法将HttpPostedFileBase存储到会话中。这没有意义。它包含一个指向HTTP Request流中文件内容的流,该流在请求结束时被垃圾收集。在存储到会话之前,您需要将其序列化为某个自定义对象。例如:

public class MyFile
{
    public string Name { get; set; }
    public string ContentType { get; set; }
    public byte[] Contents { get; set; }
}

现在继续将其存储到会话中。当然,您应该知道,通过这样做,您将整个文件内容存储到内存中,这可能不是您想要做的事情,特别是如果上传的文件可能很大。另一种可能性是将文件内容存储到像磁盘或数据库这样的可持久介质中,并将只存储到该介质的指针存储到会话中,以便以后可以检索它。

答案 1 :(得分:2)

如果你使用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);

并将其保存到文件中。

答案 2 :(得分:0)

HttpPostedFile直接从HTTP请求流中读取 它不适合重复使用。