2011-12-24 103 views
3

我必須上傳一個文件到服務器,只顯示帶有文件上傳按鈕的jsf網頁(通過http)。我必須自動化一個進程(完成java獨立進程),它會生成一個文件並將文件上傳到服務器。稍後要上傳文件的服務器不提供FTP或SFTP。有沒有辦法做到這一點?如何以編程方式將文件上傳到網站?

感謝, 裏奇

+0

你能保持工作樣例代碼,它。 – spt 2014-01-02 05:40:24

回答

7

當編程提交JSF生成表格,你需要確保你採取以下3件事帳戶:

  1. 維護HTTP會話(當然如果網站有JSF服務器端狀態保存開啓)。
  2. 發送隱藏字段的名稱/值對javax.faces.ViewState
  3. 發送虛擬按下按鈕的名稱 - 值對。

否則,該操作可能根本不會被調用。對於剩餘它與「常規」形式沒有什麼不同。流程基本如下:

  • 在窗體頁面上發送GET請求。
  • 提取JSESSIONID cookie。
  • 從響應中提取隱藏域的值javax.faces.ViewState。如有必要(確定它是否具有動態生成的名稱,因此可能會更改每個請求),請提取輸入文件字段的名稱和提交按鈕。動態生成的ID /名稱可由j_id前綴識別。
  • 準備multipart/form-data POST請求。
  • 在該請求上設置JSESSIONID cookie(如果不是null)。
  • 設置名稱 - 值對javax.faces.ViewState隱藏字段和按鈕。
  • 設置要上傳的文件。

您可以使用任何HTTP客戶端庫來執行任務。標準Java SE API爲此提供java.net.URLConnection,即pretty low level。爲了最終減少冗長的代碼,您可以使用Apache HttpClient來執行HTTP請求並管理Cookie,並使用Jsoup從HTML中提取數據。

這裏有一個開球例如,假設頁面只有一個<form>(否則你需要包括形式的Jsoup的CSS選擇器的唯一標識符):

String url = "http://localhost:8088/playground/test.xhtml"; 
String viewStateName = "javax.faces.ViewState"; 
String submitButtonValue = "Upload"; // Value of upload submit button. 

HttpClient httpClient = new DefaultHttpClient(); 
HttpContext httpContext = new BasicHttpContext(); 
httpContext.setAttribute(ClientContext.COOKIE_STORE, new BasicCookieStore()); 

HttpGet httpGet = new HttpGet(url); 
HttpResponse getResponse = httpClient.execute(httpGet, httpContext); 
Document document = Jsoup.parse(EntityUtils.toString(getResponse.getEntity())); 
String viewStateValue = document.select("input[type=hidden][name=" + viewStateName + "]").val(); 
String uploadFieldName = document.select("input[type=file]").attr("name"); 
String submitButtonName = document.select("input[type=submit][value=" + submitButtonValue + "]").attr("name"); 

File file = new File("/path/to/file/you/want/to/upload.ext"); 
InputStream fileContent = new FileInputStream(file); 
String fileContentType = "application/octet-stream"; // Or whatever specific. 
String fileName = file.getName(); 

HttpPost httpPost = new HttpPost(url); 
MultipartEntity entity = new MultipartEntity(); 
entity.addPart(uploadFieldName, new InputStreamBody(fileContent, fileContentType, fileName)); 
entity.addPart(viewStateName, new StringBody(viewStateValue)); 
entity.addPart(submitButtonName, new StringBody(submitButtonValue)); 
httpPost.setEntity(entity); 
HttpResponse postResponse = httpClient.execute(httpPost, httpContext); 
// ... 
+0

我試過這個,但徒勞無功。我設立了一個類似的虛擬網站。我收到200 OK響應,同時我提交了jsf頁面的帖子回覆。由於某種原因,它不會調用提交方法。我在服務器上提交了一個提交方法的斷點,但是調用永遠不會到達那裏。 – Richie 2011-12-25 10:07:09

+0

目前很難指出真實的問題。您是否理解代碼示例中必須更改的內容才能使其適用於特定網站? – BalusC 2011-12-25 12:44:47

+0

是。我更改了網址並提交了按鈕值以匹配我的網頁。我還更改了要上傳的文件的路徑 – Richie 2011-12-25 13:29:43

1

嘗試使用HttpClient的,here's an article我想描述你想要什麼,朝下方有一個標題爲部分「使用HttpClient的基於文件上傳」。

希望這會有所幫助。

+0

感謝隊友的答案。我曾試過這個,但由於它是一個jsf應用程序,我必須設置隱藏參數以及BalusC在他的答案中指出。 – Richie 2011-12-25 13:44:26

0

也許該網頁只是發送POST請求到服務器與表單的內容。您可以輕鬆地從Java自己發送這樣的POST請求,而無需使用該頁面。例如this article顯示了一個發送來自Java的POST請求的例子

0

您需要做的是檢查頁面上的HTML並確定發佈表單所需的參數。它可能會是這個樣子:

<form action="/RequestURL"> 
<input type=file name=file1> 
<input type=textbox name=value1> 
</form> 

此基礎上,你可以寫一些代碼做一個POST請求的網址:

String data = URLEncoder.encode("value1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8"); 
data += "&" + URLEncoder.encode("file1", "UTF-8") + "=" + URLEncoder.encode(FileData, "UTF-8"); 

// Send data 
URL url = new URL("http://servername.com/RequestURL"); 
URLConnection conn = url.openConnection(); 
conn.setDoOutput(true); 
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); 
wr.write(data); 
wr.flush(); 
wr.close(); 

記住,誰寫的頁面的人可能會做一些檢查以確保POST請求來自同一個站點。在這種情況下,您可能會遇到麻煩,並且您可能需要正確設置用戶代理。

0

您可以嘗試使用HtmlUnit。它提供了一個非常簡單的API來模擬瀏覽器操作。我已經使用這種方法來達到類似的要求。這很容易。你應該試試看。

相關問題