Yuriy Mayorov
Yuriy Mayorov

Reputation: 971

How to read HttpInputStream twice

I need to parse and custom save(not using SaveAs) HttpPostedFileBase in my asp.net mvc application.

My code is:

private ReportViewModel LoadFile(Stream stream, string fileName)
{
   MapParser mapParser = new MapParser(stream);
   try
   {
       mapParser.Parse();
   }
   ....
   stream.position = 0;
   SaveFile(memStream2, Server.MapPath("~/Uploads/Maps/" +
                (map.Id + "." + ext)));
   ....
}

public static void SaveFile(Stream inputStream, string filePath)
{
   using (Stream file = System.IO.File.Create(filePath))
   {
      inputStream.CopyTo(file);
   }
 }


LoadFile(loadMapVM.MapFile.InputStream, loadMapVM.MapFile.FileName)

So, my Parse() method works fine, but after that SaveAs method create file with 0 bytes. I think, that I should clone or reopen to start my stream after Parse(). But how can I do that?

EDIT

My MapParser code:

        public MapParser(Stream stream)
        {
            using(stream)
            {
                IWorkbook workBook = null;

                if (POIXMLDocument.HasOOXMLHeader(stream))
                    workBook = new XSSFWorkbook(stream);

                if (POIFSFileSystem.HasPOIFSHeader(stream))
                    workBook = new HSSFWorkbook(stream);

                if (workBook == null)
                    throw new MapParserException(MapParserError.InvalidFileFormat);

                mSheet = workBook.GetSheetAt(0);
            }
        }

    public void Parse()
    {
        mData = new Map();

        mData.UnitCode = mSheet.GetRow(0).GetCell(5).GetSafeValue();
        if (mData.UnitCode == "")
            throw new MapParserException(MapParserError.NoUnitCode, 0, 5);

        ....
    }

Upvotes: 0

Views: 1650

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1063338

In the general case, it should not be assumed that Streams are repeatable; this applies in particular when talking about data coming over the wire. If you read the data in Parse, then you have consumed the data: it is gone.

Options:

  • buffer all the data in memory (Stream.CopyTo into a MemoryStream) - possible if you restrict it to moderate sizes, but not a good option if the data could be huge
  • perform the Parse while writing to the file-system; efficient but difficult to implement
  • buffer the data to disk (basically do the SaveFile first), then check the contents that you wrote (write it to a different location, then delete the file if the contents are no good, or move the file if the contents are fine)

Upvotes: 2

Related Questions