通过HTTP发送XML的问题

时间:2011-08-10 12:32:05

标签: java php xml

我想要一个解析各种RSS源并将信息发送到远程服务器的应用程序。信息以xml格式通过http发送。起初我尝试在我自己的服务器上部署这个应用程序,所以我使用Java Tips的this tutorial中显示的方法发送xml。这是我从代码中复制的代码:

第一种方法

    String strURL = "http://localhost/readme/readme_xml";
    String strXMLFilename = "output.xml";
    File input = new File(strXMLFilename);


    PostMethod post = new PostMethod(strURL);
    post.setRequestEntity(new InputStreamRequestEntity(
            new FileInputStream(input), input.length()));
    post.setRequestHeader(
            "Content-type", "text/xml; charset=ISO-8859-1");
    HttpClient httpclient = new HttpClient();
    try {

        int result = httpclient.executeMethod(post);            
        System.out.println("Response status code: " + result);            
        System.out.println("Response body: ");
        System.out.println(post.getResponseBodyAsString());            
    } finally {
        post.releaseConnection();
    }

这非常有效(我甚至使用localhost之外的远程服务器进行了测试)。然后,不知何故,我无法使用自己的服务器来部署此应用程序,因此我决定迁移到Google Apps Engine。正如我们所知,关于它的一件事是,并非所有库都被允许进入环境。所以我尝试在ExampleDepot.com中显示的另一种方法(我找不到确切的网址),如下所示:

第二种方法

try {
           /* fill up this url with the remote server url */
            URL url = new URL("http://localhost/readme/readme_xml");
            FileReader fr = new FileReader("output.xml");
            char[] buffer = new char[1024*10];
            int len = 0;
            if ((len = fr.read(buffer)) != -1){
            /* send http request to remote server */
                URLConnection conn = url.openConnection();
                conn.setRequestProperty("Content-Type","text/xml;charset=ISO-8859-1"); /* need to specify the content type */
                conn.setDoOutput(true);
                conn.setDoOutput(true);
                PrintWriter pw = new PrintWriter(conn.getOutputStream());
                pw.write(buffer, 0, len);
                pw.flush();
                /* receive response from remote server*/
                BufferedReader bf = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String input = null;
                while ((input = bf.readLine()) != null){
                    System.out.println(input);
                }
            }

        } catch (MalformedURLException e) {
                e.printStackTrace();
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
                e.printStackTrace();
        }
    }

第二种方法虽然不起作用并且给出以下错误(我使用SimpleXMLElement(php)对象来解析远程主机中的xml):

Error message from remote server

这是来自远程服务器的php代码(在这里,我只是希望SimpleXMLElement解析xml而不做任何其他想象的事情)

$xml = new SimpleXMLElement('php://input', NULL, TRUE);
   foreach ($xml -> attributes() as $name => $val){
   echo "[".$name."] = ".$val."\n";
   }

我认为这个问题的原因是故障xml文件(因为eclipse IDE指示存在“1字节utf-8序列的无效字节1”的错误)。然后我使用相同的输入xml文件到第一个方法,但它仍然完美。

那么我需要对第二种方法进行调整吗?或者我可以使用任何其他方法将xml文件发送到远程服务器?如果我需要添加其他一些细节,请告诉我。谢谢你的帮助。


注意:我实际上是通过使用评论中给出的解决方案解决了这个问题。我没有使用答案中建议的方法,即使这些答案非常有用。所以,我没有从给出的答案中选出最佳答案。尽管如此,我仍然感谢你的所有帮助,因此值得我的支持。干杯!

3 个答案:

答案 0 :(得分:1)

我猜您需要将内容类型更改为multipart / form-data。 See an already answered question详细说明。文件上传将在本示例的底部讨论

答案 1 :(得分:1)

作为第一个答案建议,我会用InputStream读取文件。从字节转换为char并再次返回是不必要的并且是错误的来源。另外,请验证输入文件是否确实使用了ISO-8859-1编码。

更新:

使用FileReader时,您接受默认编码(即如何从chars制作bytes)。此编码必须与用于输入文件的编码匹配,否则会导致结果损坏的风险很大。对于不同的平台,默认的Java编码是不同的,因此依赖它通常不是一个好主意。

在你的第二个例子中,没有理由将文件作为字符读取,因为无论如何它将作为字节在线路上发送。一直使用字节流也避免了编码问题(除了内容类型标题中的信息)。

答案 2 :(得分:0)

除非您正在阅读文本文件,否则永远不会将文件读取为字符。 xml 不是文本,它是二进制格式。使用普通的InputStreams和byte [] s复制文件。

另外,正如@ beny23在他的评论中所建议的,确保你总是使用循环复制流,而不是单个read()(即使你的缓冲区足够大,也不能保证InputStream会给你一次调用中的所有字节,即使对于FileInputStream也是如此。