【问题标题】:How can I save PL/SQL output (clob) as an XML file?如何将 PL/SQL 输出 (clob) 保存为 XML 文件?
【发布时间】:2013-03-14 13:02:12
【问题描述】:

在这个阶段我觉得自己很愚蠢,因为这似乎不是我应该与之抗争的任务,但是经过短暂的睡眠和 1000 个想法在我脑海中闪过,我想我现在是锅里的青蛙了隧道视觉病毒使解决方案变得模糊。如下:

我在 PL/SQL 中有一个查询,它使用 DBMS_XMLGEN.getxml 从几个表中将数据选择为 XML 格式(1 行,1 列是 CLOB 类型)。这非常有效。

我的问题在于将此 XML 输出返回到 C#,并询问用户他想在他的个人电脑上将此输出保存为 output.xml 文件的位置。

我将 ASP.net 与 JQuery (AJAX) 一起使用,因此在单击链接时发布到 .aspx 页面并使用返回的数据(在此实例中来自查询的 xml)进行保存。 将 OLEDB 命令与 OLEDB 数据读取器一起使用似乎不是正确的方法...

这样做的最佳方法是什么?我在.net 中的序列化工作不多,但我认为这是最好的方法(根据我所做的研究)?有没有人举例说明如何在我的情况下做到这一点?

我的想法基本上是在内存中创建这个输出/文件,询问用户要将其保存在哪里,将其保存为 .xml 文件并清除内存。

更新: 好的,我设法创建了一个 XMLDocument,它很容易接受来自我的查询的 xml 输出。我怎样才能从用户那里获得关于在他的电脑上保存这个文件的位置的输入?

到目前为止我的代码:

Javascript:

function XML_ExportAppRestrictions() {
try {

    var data = {"action": "exportAppRestrictions"};

    var returned = AjaxLoad('Modules/Common/Common.aspx', null, data, null, null, false);

    if (returned.toString().toUpperCase().substring(0, 5) == "ERROR") {
        return;
    }
    else {
        // should the file be saved here or in my aspx page using xmldoc.save?
        // Using xmldoc.save will only be able to save the file on the server yes?
    }
}
    catch (ex) {
        alert(ex.Message);
    }
}

平均售价:

if (Request["action"] == "exportAppRestrictions")
    {

        // Create and open DB connection
        conn.ConnectionString = SG_Common.CommonClass.NetRegUDL;
        common.OpenDBConnection(ref conn);

        // Create command and set SQL statement
        cmd.Connection = conn;
        cmd.CommandType = System.Data.CommandType.Text;
        // select text was removed below due to it's length
        cmd.CommandText = "select x as AppRestrictions from dual";

        rd = cmd.ExecuteReader();

        if (rd.HasRows)
        {
            if (rd.Read())
            {
                str = rd["AppRestrictions"].ToString();
            }
        }
        rd.Close();

        System.Xml.XmlDocument xmldoc = new System.Xml.XmlDocument();
        xmldoc.InnerXml = str;
        xmldoc.Save("c:\\xmltest.xml");

        goto Done;
    }

    // Done runs in a seperate try/catch statement and only returns data to the calling js function.
    Done:
        Response.Write(str);

【问题讨论】:

  • 我的答案更新 1 错误地用于 Windows SaveFileDialog。更新 2 显示了具有内容处置的 Web 响应代码。

标签: c# javascript jquery asp.net


【解决方案1】:

XML 应该只是 UTF8 纯文本。我对对象使用了序列化。也许有人会纠正我,但我发现没有必要对纯文本或二进制数据使用序列化。

为了让这些数据通过内存,有一个很好的 StackOverflow answer here 展示了如何使用 MemoryStream 和字节缓冲区。

因为如果你能把它放到一个 byte[] 缓冲区中,你就可以做到something like this:

public bool SaveDocument( Byte[] docbinaryarray, string docname)
{
    string strdocPath;
    strdocPath = "C:\\DocumentDirectory\\" + docname;
    FileStream objfilestream =new FileStream(strdocPath,FileMode.Create,FileAccess.ReadWrite);
    objfilestream.Write(docbinaryarray,0,docbinaryarray.Length);
    objfilestream.Close();
    return true;
}

参考here for some more info on System.IO methods,例如:

StreamWriter writer = new StreamWriter("c:\\KBTest.txt");
writer.WriteLine("File created using StreamWriter class.");
writer.Close();
this.listbox1.Items.Clear();
addListItem("File Written to C:\\KBTest.txt");

更新 1(Windows):

(我以为你在找System.Windows.Forms.SaveFileDialog

这是 MSDN 示例代码:

private void button2_Click(object sender, System.EventArgs e)
{
   // Displays a SaveFileDialog so the user can save the Image
   // assigned to Button2.
   SaveFileDialog saveFileDialog1 = new SaveFileDialog();
   saveFileDialog1.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif";
   saveFileDialog1.Title = "Save an Image File";
   saveFileDialog1.ShowDialog();

   // If the file name is not an empty string open it for saving.
   if(saveFileDialog1.FileName != "")
   {
      // Saves the Image via a FileStream created by the OpenFile method.
      System.IO.FileStream fs = 
         (System.IO.FileStream)saveFileDialog1.OpenFile();
      // Saves the Image in the appropriate ImageFormat based upon the
      // File type selected in the dialog box.
      // NOTE that the FilterIndex property is one-based.
      switch(saveFileDialog1.FilterIndex)
      {
         case 1 : 
             this.button2.Image.Save(fs, 
            System.Drawing.Imaging.ImageFormat.Jpeg);
         break;

         case 2 : 
         this.button2.Image.Save(fs, 
         System.Drawing.Imaging.ImageFormat.Bmp);
         break;

         case 3 : 
         this.button2.Image.Save(fs, 
                System.Drawing.Imaging.ImageFormat.Gif);
         break;
      }

   fs.Close();
   }
}

而且,正如它所说,您需要注册事件处理程序:

this.button2.Click += new System.EventHandler(this.button2_Click);

更新 2(网络):

好的,我知道您实际上是在寻找 Web 解决方案。我在想 Windows 而不是 Web。 Here's what you have to do on the Web side.这是一个VB.NET的例子,但我假设你可以翻译:

string FileName = "Hello.doc";
string Filename = strFileName.Substring(0, FileName.LastIndexOf("."));                      
Response.AppendHeader("Content-Disposition", "attachment; filename=" + FileName);
Response.TransmitFile(Server.MapPath("~/Folder_Name/" + FileName));
Response.End();

我已经多次对这种方法进行了变体。您将 XML 文件发送回用户的浏览器。一旦它到达那里,用户必须决定如何处理它(通常是“打开这个文件,还是保存它?”)。这是在浏览器的控制之下。

您可以通过包含一个内容类型标题来帮助浏览器,该标题告诉浏览器它正在查看哪种文件,以及它应该尝试用什么打开它。所以这个标题会要求它调用 Excel:

Response.AppendHeader("Content-Type", "application/vnd.ms-excel");

您会经常看到 application/pdf,它会打开 Adob​​e Reader 或用户正在使用的任何其他 PDF 阅读器。在这里,您将要使用内容类型“text/xml”。这里的内容类型不太重要,因为我们打算让用户保存文件,而不是使用应用程序打开它。

内容配置“附件”与“内联”存在一些问题。尝试两种方式,看看哪一种更适合你。其中一个(我不记得是哪个)基本上忽略了您发送的建议文件名,而是使用您的 ASP 页面的名称。很烦人。 Firefox 至少将其记录为一个错误,IE 显然只是将其视为另一个“功能”。

【讨论】:

  • 感谢 ctriticalfix 的回复!我想给 +1,但我是 Stackoverflow 的新手,直到我获得 15+ 的声誉...:-/
  • 我确实遇到了这个问题的解决方案,我会在下面发布答案,以防其他人将来需要这个。
【解决方案2】:

在用户交互方面使用 Jquery (AJAX) 有其局限性(具体参考保存对话框 - 即在我的示例中向 asp 页面发送请求,并期望文件 [或在我的情况下为内存流) ] 返回,并想询问用户他想将其保存在哪里 - 因此不在服务器上)。

我发现了一种解决方法,因为使用 AJAX 进行网络相关调用是我的强项。正如这篇文章中提到的,还有一些改进的空间,但对我来说效果很好,因此允许使用 response.write (x) 返回我的 XML 数据,并且这个“hack”允许用户将 XML 文件保存在他想要的任何地方:

Javascript 源代码:

jQuery.download = function (url, data, method) {
//url and data options required
if (url && data) {
    //data can be string of parameters or array/object
    data = typeof data == 'string' ? data : jQuery.param(data);
    //split params into form inputs
    var inputs = '';
    jQuery.each(data.split('&'), function () {
        var pair = this.split('=');
        inputs += '<input type="hidden" name="' + pair[0] + '" value="' + pair[1] + '" />';
    });
    //send request
    jQuery('<form action="' + url + '" method="' + (method || 'post') + '">' + inputs + '</form>')
    .appendTo('body').submit().remove();
};
};

ASP 回报:

Response.Clear();
Response.ContentType = "text/xml";
Response.AddHeader("Content-disposition", "attachment; filename=test.xml");
Response.Write(yourXMLstring);

使用示例(javascript调用):

$.download("your_url_here", html_url_based_parameters_if_needed_here);

在这里获得了这篇有用的帖子:http://www.filamentgroup.com/lab/jquery_plugin_for_requesting_ajax_like_file_downloads/

希望这对将来的人有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 2010-12-03
    • 1970-01-01
    • 2012-10-03
    相关资源
    最近更新 更多