4

在这个阶段我觉得很愚蠢,因为这似乎不是我应该与之抗争的任务,但是经过短暂的睡眠和 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);
    }
}

ASP:

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);
4

2 回答 2

1

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

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

因为如果您可以将其放入 byte[] 缓冲区,则可以执行以下操作:

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;
}

有关 System.IO 方法的更多信息,请参阅此处,例如:

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。 这是您必须在 Web 端执行的操作。 这是一个 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");

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

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

于 2013-03-14T14:14:19.390 回答
0

使用 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();
};
};

平均售价回报:

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/

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

于 2013-03-18T10:25:49.510 回答