如何使用JSoup发布文件?

15

我正在使用以下代码通过JSoup提交值:

Document document = Jsoup.connect("http://www......com/....php")
                    .data("user","user","password","12345","email","info@tutorialswindow.com")
                    .method(Method.POST)
                    .execute()
                    .parse();

我现在也想提交一个文件,就像一个带有文件字段的表单。这是否可能?如果是,那么如何实现?

3个回答

20

自Jsoup 1.8.2(于2015年4月13日发布)起,可以通过新的data(String, String, InputStream)方法来支持此功能。

String url = "http://www......com/....php";
File file = new File("/path/to/file.ext");

Document document = Jsoup.connect(url)
    .data("user", "user")
    .data("password", "12345")
    .data("email", "info@tutorialswindow.com")
    .data("file", file.getName(), new FileInputStream(file))
    .post();
// ...

在旧版本中,不支持发送multipart/form-data请求。你最好使用一个完整的HTTP客户端来进行此操作,例如Apache HttpComponents Client。最终,您可以将HTTP客户端响应作为String获取,以便将其馈送到Jsoup#parse()方法。

String url = "http://www......com/....php";
File file = new File("/path/to/file.ext");

MultipartEntity entity = new MultipartEntity();
entity.addPart("user", new StringBody("user"));
entity.addPart("password", new StringBody("12345"));
entity.addPart("email", new StringBody("info@tutorialswindow.com"));
entity.addPart("file", new InputStreamBody(new FileInputStream(file), file.getName()));

HttpPost post = new HttpPost(url);
post.setEntity(entity);

HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(post);
String html = EntityUtils.toString(response.getEntity());

Document document = Jsoup.parse(html, url);
// ...

自 JSoup 1.12.1 起,即使在表单数据中没有涉及文件,也可以发送 multipart/form-data 请求。请参见此处的示例:https://stackoverflow.com/a/63100270/363573。 - Stephan

8

这个被接受的答案在写作时是正确的,但自那时以来,JSoup已经发展并且自1.8.2版本起可以将文件作为多部分表单的一部分发送:

File file1 = new File("/path/to/file");
FileInputStream fs1 = new FileInputStream(file1);

Connection.Response response = Jsoup.connect("http://www......com/....php")
    .data("user","user","password","12345","email","info@tutorialswindow.com")            
    .data("file1", "filename", fs1)
    .method(Method.POST)
    .execute();

1
JSoup 1.12.1引入了对多部分表单的完全支持,只要设置了内容类型标头。详见此处:https://stackoverflow.com/a/63100270/363573 - Stephan

1
这篇文章让我找到了正确的方向,但我不得不调整已发布答案以使其适用于我的使用情况。这是我的代码:
        FileInputStream fs = new FileInputStream(fileToSend);
        Connection conn = Jsoup.connect(baseUrl + authUrl)
                .data("username",username)
                .data("password",password);
        Document document = conn.post();

        System.out.println("Login successfully! Session Cookie: " + conn.response().cookies());


        System.out.println("Attempting to upload file...");
        document = Jsoup.connect(baseUrl + uploadUrl)
                .data("file",fileToSend.getName(),fs)
                .cookies(conn.response().cookies())
                .post();

基本区别在于我首先登录到网站,保留响应中的cookie (conn),然后再将其用于随后的文件上传。
希望对大家有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接