【问题标题】:Read, modify, and output an in-memory binary stream读取、修改和输出内存中的二进制流
【发布时间】:2017-04-19 15:27:13
【问题描述】:

我的最终目标是上传一个 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;
    }

【问题讨论】:

  • 您能否在调用 CopyTo 方法之前确认 fsTemplate 位置是否为 0
  • 它是否被初始化为 0?这是我创建它并将其传递给 Parse 方法的地方: Stream stream = new MemoryStream(data);

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


【解决方案1】:

我建议调用 writer.Flush() 来强制它写入缓冲数据。或者用“using”封装 writer instancination,这最终会做同样的事情。

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;

【讨论】:

    【解决方案2】:

    这是如何完成的。

    创建 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 ENTITY DATA MODEL

    这是你的看法:

    @{
        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>
    

    【讨论】:

    • 感谢您的回复,这可能对某人有所帮助,但这并不是我真正想要解决的问题。我的上传和存储过程已经建立并且可以正常工作,但是我无法修改文件并返回我的文件的非损坏更新版本。我不能将任何东西存储到磁盘上,即使是暂时的,所以所有的东西都必须在内存中完成。我更新了我的问题以包含正在运行的代码,并将纳入 Radislav Kireev 的输入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 2018-06-06
    相关资源
    最近更新 更多