读取,修改和输出内存中的二进制流

时间:2017-04-19 15:27:13

标签: c# asp.net-mvc system.io.file

我的最终目标是上传rtf文档并将二进制内容存储在表中,然后检索该模板的内容,根据一些预定义的标签替换一些文本,并触发浏览器下载更新的模板。我最初的目标是上传一个rtf文件(工作),通过我的解析方法运行它(没有任何更改),并使用原始模板成功打开下载的文件。现在下面的所有内容都在工作,除了生成的文件已损坏(我不确定我的流是否被正确处理)。我应该深入研究System.IO以更好地理解内存流等,但这是这个项目中我唯一需要做这样的事情的地方,所以我试图找到一个快速的解决方案。

public static Stream ParseFile(Stream fsTemplate)
    {
        // create MemoryStream to copy template into and modify as needed
        MemoryStream doc = new MemoryStream();

        // copy template FileStream into document MemoryStream
        fsTemplate.CopyTo(doc);
        doc.Position = 0;

        string docText = string.Empty;
        using (StreamReader reader = new StreamReader(doc))
        {
            // doctText appears to look how I'd expect when I debug
            docText = reader.ReadToEnd();
            reader.Close();
        }

        //replace text in 'docText' as neccessary (not yet implemented)

        // This is where I'm not really clear what I should be doing differently
        var ms = new MemoryStream();
        StreamWriter writer = new StreamWriter(ms);
        writer.Write(docText);
        ms.Position = 0;

        return ms;
    }

这是我的控制器,它从数据库中检索二进制数据(上传的rtf模板),调用上述方法,并将文件流返回给浏览器

public FileStreamResult Parse(int id)
    {
        byte[] data = Context.Templates.Find(id).BinaryData;
        Stream stream = new MemoryStream(data);

        var updatedStream = Tools.ParseFile(stream);

        return File(updatedStream, "application/rtf", "temp.rtf");
    }

我用这段代码替换了我的StreamWriter,现在它正在按照我的预期工作。我仍然不确定我是否正确处理了我的溪流。

byte[] buffer = Encoding.ASCII.GetBytes(docText);
        MemoryStream ms = new MemoryStream(buffer);

完整代码:

public static Stream ParseFile(Stream fsTemplate)
    {
        // create MemoryStream to copy template into and modify as needed
        MemoryStream doc = new MemoryStream();

        // copy template FileStream into document MemoryStream
        fsTemplate.CopyTo(doc);
        doc.Position = 0;

        string docText = string.Empty;
        using (StreamReader reader = new StreamReader(doc))
        {
            // doctText appears to look how I'd expect when I debug
            docText = reader.ReadToEnd();
            reader.Close();
        }

        //replace text in 'docText' as neccessary (not yet implemented)

        byte[] buffer = Encoding.ASCII.GetBytes(docText);
        MemoryStream ms = new MemoryStream(buffer);

        return ms;
    }

2 个答案:

答案 0 :(得分:0)

我建议调用writer.Flush()强制它写入缓冲数据。或者用“使用”包围编写器实例,最后也会这样做。

public static Stream Parse(Stream fsTemplate){...    

// This is where I'm not really clear what I should be doing differently
var ms = new MemoryStream();
StreamWriter writer = new StreamWriter(ms);
writer.Write(docText);
writer.Flush();  // <-- here
ms.Position = 0;

答案 1 :(得分:0)

以下是如何完成的。

创建rtf文档并将其另存为AAnRTF.txt 内容:

<div>
This is an rtf document
<div>

这是你的控制器和方法:

public class HomeController : Controller
{
    public ActionResult UploadFilePost(string SubmitButton, HttpPostedFileBase file)
    {
        if (SubmitButton == "Upload RTF")
        {
            //I use BreazEntities13, you will use what comes out of the EDMX wizard
            //EDMX is easy please try it
            byte[] byteContent;
            Stream aStream = file.InputStream;
            MemoryStream memoryStream = new MemoryStream();
            aStream.CopyTo(memoryStream);
            byteContent = memoryStream.ToArray();

            ImportMod imsk = new ImportMod
            {
                Contents = byteContent,
                ContentType = "text/plain"
            };
            using (BreazEntities13 entity = new BreazEntities13())
            {
                entity.ImportMods.Add(imsk);
                entity.SaveChanges();
            }
        }
        else if (SubmitButton == "Download RTF")
        {
            //get documnet
            ImportMod kit = new ImportMod();
            using (BreazEntities13 entity = new BreazEntities13())
            {
                kit = entity.ImportMods.FirstOrDefault();  //! GETS only the first documument
            }

            //modify file -credit to other stack o pages
            //eg http://stackoverflow.com/questions/9174402/replacing-the-innertext-of-an-xml-node-element
            XmlDocument doc = new XmlDocument();
            string xml = Encoding.UTF8.GetString(kit.Contents);
            doc.LoadXml(xml);
            doc.SelectSingleNode("div").InnerText = "Replace text, xmldocument is similiar to rtf or choose a diff type";
            byte[] bytes = Encoding.Default.GetBytes(doc.OuterXml);

            this.ControllerContext.HttpContext.Response.ClearContent();
            this.ControllerContext.HttpContext.Response.ContentType = "text/plain";
            this.ControllerContext.HttpContext.Response.AddHeader("content-disposition",
            "attachment; filename=" + "AAnRTF.txt");
            this.ControllerContext.HttpContext.Response.BinaryWrite(bytes);
            this.ControllerContext.HttpContext.Response.End();
        }

        return View("UploadFile");
    }

    public ActionResult UploadFile()
    {
        return View();
    }

创建一个表来保存文件:

GO

/****** Object:  Table [dbo].[ImportModStarterKit]    Script Date: 4/19/2017 10:25:48 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[ImportMod](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Contents] [varbinary](max) NULL,
    [ContentType] [nvarchar](2048) NULL,
 CONSTRAINT [PK_ImportModStarterKit] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

为此表创建一个edmx ADO.NET实体数据模型

以下是您的观点:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>UploadFile</title>
</head>
<body>
    <div>
        @using (Html.BeginForm("UploadFilePost",
        "Home",
        FormMethod.Post,
        new { enctype = "multipart/form-data" }))
        {
            <div class="commonImportPageHeight">
                Import Cases
                <div class="boxAroundFileUpload">
                    <input type="file" name="file" id="file" class="uploadFileWidth" /><br>
                    <input type="submit" name="SubmitButton" value="Upload RTF" />
                    <br/>
                    <input type="submit" name="SubmitButton" value="Download RTF" />
                    <br>
                </div>
            </div>

        }

    </div>
</body>
</html>