2011-12-24 92 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来模拟浏览器操作。我已经使用这种方法来达到类似的要求。这很容易。你应该试试看。

相关问题