2011-08-10 73 views
1

我想要一個解析各種RSS源並將信息發送到遠程服務器的應用程序。信息以http格式以xml格式發送。起初我試圖在自己的服務器上部署這個應用程序,所以我使用Java Tips中的this tutorial所示的方法發送xml。這裏是我的代碼是從示例複製:通過HTTP發送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(); 
    } 

這工作完全(我甚至使用本地主機之外的遠程服務器進行測試)。然後,我無法使用自己的服務器部署此應用程序,因此我決定遷移到Google Apps Engine。正如我們所知,有一件事是,並非所有的圖書館都被允許進入環境。所以,我嘗試在ExampleDepot.com所示的另一種方法(我無法找到其確切的URL雖然)如下:

第二種方法

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代碼(在這裏,我只想辛pleXMLElement解析XML而不做其他任何花哨的現在)

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

我想到了這個問題的原因是出現故障的XML文件(因爲eclipse IDE指示有1個字節的UTF的「無效字節1錯誤-8序列「)。然後我使用與第一種方法相同的確切輸入xml文件,但它仍然完美。

那麼我需要對第二種方法進行什麼調整?或者是否有任何其他方法可以用來將xml文件發送到遠程服務器?讓我知道是否需要添加其他細節。謝謝你的幫助。


注:我實際上通過使用評論中給出的解決方案解決了這個問題。我沒有使用答案中提出的方法,即使這些答案非常有用。所以,我沒有從給出的答案中選出最好的答案。儘管如此,我仍然感激你的所有幫助,因此應得到我的讚賞。乾杯!

+2

你的輸入文件有多大(輸出xml)。在第二種解決方案中,您只能讀取文件的前10240個字節。另外,您應該關閉輸出流,而不是刷新打印流。 – beny23

+1

就像beny23告訴的,你沒有閱讀整個XML。將'if'語句轉換爲'while'循環並將網絡代碼移出循環。同時關閉'PrintWriter'。 – asgs

+0

@ beny23和噓我只是遵循你的建議和漂亮的大部分東西(仍然堅持另一件事,但說錯誤消失)。我沒有意識到我只讀了有限的流。所以爲你們兩個而奮鬥!謝謝! – vandershraaf

回答

0

從不讀取文件爲字符,除非您正在讀取文本文件。 xml 不是文本,它是一種二進制格式。使用普通的InputStreams和byte [] s複製文件。

另外,如@ beny23在他的評論中建議的,確保你總是使用循環複製流,而不是一個read()(即使你的緩衝區足夠大,但不能保證InputStream會給你所有的字節在一次調用中,即使是FileInputStream也是如此)。

+0

當然XML是文本。你在想什麼XML? –

+0

哇,我喜歡downvotes!請認真閱讀xml格式。那麼,一旦代碼被修復,請刪除你的提議,並且你意識到我的答案是正確的。 @Ryan Stewart - 請在發表評論之前做一些背景閱讀。 – jtahlborn

+0

給所有困惑的人,是的,我明白,XML看起來像文本。然而,如果你理解解析一個xml文檔的所有細節,你就會明白,只是盲目地將一個xml文檔轉換爲字符是一種破壞文檔的肯定的方式。 – jtahlborn

1

作爲第一個答案,我會用InputStream讀取文件。從字節轉換爲字符並返回是不必要的,也是錯誤的根源。另外,請確認輸入文件確實使用ISO-8859-1編碼。

UPDATE:

當使用FileReader,你接受默認的編碼(即如何從byteschars)。此編碼必須與用於輸入文件的編碼匹配,否則結果已損壞的風險很大。對於不同的平臺,默認的Java編碼是不同的,所以依靠它通常不是一個好主意。

在第二個示例中,沒有理由將該文件讀爲字符,因爲它將作爲字節以字節形式發送。一路使用字節流也可以避免編碼問題(除了內容類型頭中的信息)。

+0

你能解釋更多關於這個? – vandershraaf