如何以编程方式将文件上传到网站?

时间:2011-12-24 10:03:50

标签: java jsf file-upload

我必须将文件上传到服务器,该服务器仅显示带有文件上传按钮(通过http)的jsf网页。我必须自动化一个进程(作为java独立进程完成),它生成一个文件并将文件上传到服务器。然后,必须上传文件的服务器不提供FTP或SFTP。有没有办法做到这一点?

谢谢, 里奇

5 个答案:

答案 0 :(得分:7)

以编程方式提交JSF生成的表单时,您需要确保考虑以下3项内容:

  1. 维护HTTP会话(当然,如果网站启用了JSF服务器端状态保存)。
  2. 发送javax.faces.ViewState隐藏字段的名称 - 值对。
  3. 发送虚拟按下的按钮的名称 - 值对。
  4. 否则可能根本不会调用该操作。对于残余,它与“常规”形式没有区别。流程基本如下:

    • 使用表单在页面上发送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);
    // ...
    

答案 1 :(得分:1)

尝试使用HttpClient,我认为here's an article描述了你想要的东西,在底部有一个标题为“使用基于HttpClient的FileUpload”的部分。

希望这有帮助。

答案 2 :(得分:0)

可能该网页只是向表单内容发送POST请求。您可以自己从Java轻松发送此类POST请求,而无需使用该页面。例如,this article显示了从Java发送POST请求的示例

答案 3 :(得分:0)

您需要做的是检查页面上的HTML并找出发布表单所需的参数。它可能看起来像这样:

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

基于此,您可以编写一些代码来对URL进行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请求来自同一站点。在这种情况下,您可能遇到麻烦,可能需要正确设置用户代理。

答案 4 :(得分:0)

您可以尝试使用HtmlUnit。它提供了一个非常简单的API来模拟浏览器操作。我已经将此方法用于类似的要求。这很容易。你应该试一试。