【问题标题】:How to join javascript fetch function, multipart/formadata and post request to upload file?如何加入 javascript 获取功能、多部分/表单数据和发布请求以上传文件?
【发布时间】:2019-08-27 10:15:23
【问题描述】:

我想用 Java 编写程序,使用 Selenium 和 executeAsyncScript() 函数将文件上传到服务器。当我手动上传文件时,Google Chrome DevTools 中的请求如下所示:Google Chrome Request

在我的代码中,我有这样的片段,但它不起作用。代码如下:

private void uploadFilesByRest(JSONObject operat) {
    if (operat != null) {
        List<Document> documentsToUpload = config.getOrder().getDocument();
        for (Document document : documentsToUpload) {
            Path pdfPath = Paths.get(document.getPathToFile());
            try {
                byte[] pdfByteArray = Files.readAllBytes(pdfPath);
                sendPdf(jsEngine, pdfByteArray);
            } catch (Exception exc) {
                System.out.println(exc.getMessage());
                LOGGER.error("Wystąpił błąd podczas konwersji pliku pdf na tablicę bajtów");
                System.out.println("Wystąpił błąd podczas konwersji pliku pdf na tablicę bajtów");
            }

        }
    } else {
        LOGGER.error("Operat przekazany jako argument do funkcji ładującej pliki do dokumentów składowych ma wartość NULL");
        System.out.println("Operat przekazany jako argument do funkcji ładującej pliki do dokumentów składowych ma wartość NULL");
    }
}

public static JSONObject sendPdf(JavascriptExecutor jsEngine, byte[] pdfBlob) {
    Object rsult = jsEngine.executeAsyncScript(
            " var callback = arguments[arguments.length - 1];\n" +
                    "var blob = new Blob([" + pdfBlob + "], {type : 'application/pdf'}); \n" +
                    "var formData = new FormData();\n" +
                    "\n" +
                    "formData.append('NazwaPliku', 'obl_001_P.2413.2001.12.pdf');\n" +
                    "formData.append('RodzajOpracowaniaDokumentu', '100065');\n" +
                    "formData.append('OwnerId', '54448');\n" +
                    "formData.append('Owner', 'szkice');\n" +
                    "formData.append('Plik', blob);\n" +
                    "formData.append('files', blob);\n" +
                    "\n" +
                    "fetch('https://gis.tarnogorski.pl//api/archiwista/dokument/dodaj', {\n" +
                    "method: 'post',\n" +
                    " headers: {\n" +
                    "'Content-type': 'multipart/form-data',\n" +
                    "}, \n" +
                    "body: formData \n" +
                    " })\n" +
                    ".then(res => res.text())\n" +
                    ".then(res => {\n" +
                    "console.log('pobrane dane:');\n" +
                    "console.log(res);\n" +
                    "callback(res);\n" +
                    "}).catch(error => console.log('Błąd: ', error));"
    );

    JSONObject json = new JSONObject();
    json.put("data", rsult);

    return json;
}

我的问题是我应该如何设置从 Java 到 JS 的字节数组以及如何正确创建 FormData(在 Google Chrome DevTools 中是 multipart/form-data)?现在我的函数返回错误“org.openqa.selenium.JavascriptException:SyntaxError:非法字符”。感谢您的帮助。

【问题讨论】:

  • 您在这里使用 Selenium 会使事情复杂化。似乎您应该只使用 Java 来发送表单数据/标题。
  • 也许可以试试 atob 和 btoa 的 java 等价物。

标签: javascript java selenium


【解决方案1】:

我已经有了答案。下面的代码工作正常。最后我只使用 java HttpClient 类。

private static final String URL = "https://gis.tarnogorski.pl/e-uslugi/portal-archiwisty";
private static final String password = "Tgeodezja11";
private static final String user = "F_OS_ABRZEZINA";
private static WebDriver driver;
private static final String iemz = "P.2413.2004.5";
private static final String forUpdate = "P.2413.2004.5_1";

public static void main(String[] args) throws JsonProcessingException, InterruptedException {
    System.setProperty("webdriver.gecko.driver", ".\\webdriver\\geckodriver-v0.23.0-win64\\geckodriver.exe");
    driver = new FirefoxDriver();
    driver.navigate().to(URL);
    WebDriverWait wait = new WebDriverWait(driver, 40);
    try {
        System.out.println("Oczekiwanie na formularz logowania");
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(FormEnum.FORMULARZ_LOGOWANIA.getxPath())));
        logIn();
        System.out.println("I'm in.....");

        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(FormEnum.OKONO_GLOWNE.getxPath())));
        try {
            byte[] pdfByteArray = Files.readAllBytes(Paths.get("D:\\Pobrane\\obl_001_P.2413.2001.12.pdf"));

            HttpClient client = new DefaultHttpClient();
            HttpContext localContext = new BasicHttpContext();

            HttpPost post = new HttpPost("https://gis.tarnogorski.pl//api/archiwista/dokument/dodaj");

            Set<Cookie> cookies = driver.manage().getCookies();
            Object[] myArr = cookies.toArray();
            String value1 = myArr[0].toString();
            String ssid = value1.split(";")[0].split("=")[1];
            String domain = value1.split(";")[2].split("=")[1];
            String value3 = myArr[2].toString();
            String sspid = value3.split(";")[0].split("=")[1];
            String value4 = myArr[3].toString();
            String currentSelected = value4.split(";")[0].split("=")[1];
            CookieStore cookieStore = new BasicCookieStore();
            BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", ssid);
           // cookie.setAttribute("currentSelectedSymfonyPortalRouteAlias", currentSelected);
          //  cookie.setAttribute("lastLogUser", "F_OS_ABRZEZINA");
           // cookie.setAttribute("ss-pid", sspid);
            cookie.setPath("/");
          //  cookie.setSecure(true);
            cookie.setDomain(domain);
            CookieStore cookieStore1 = new BasicCookieStore();
            CookieStore cookieStore2 = copySeleniumCookies(cookies, cookieStore1);
            localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore2);

            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);

            builder.addTextBody("NazwaPliku", "obl_001_P.2413.2001.12.pdf");
            builder.addTextBody("RodzajOpracowaniaDokumentu", "100065");
            builder.addTextBody("OwnerId", "54448");
            builder.addTextBody("Owner", "szkice");
            builder.addBinaryBody("Plik", pdfByteArray, ContentType.DEFAULT_BINARY, "obl_001_P.2413.2001.12.pdf");
            builder.addBinaryBody("files", pdfByteArray, ContentType.DEFAULT_BINARY, "obl_001_P.2413.2001.12.pdf");

            UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(user, password);
            Header header = new BasicScheme().authenticate(credentials, post);
            post.addHeader(header);

            HttpEntity entity = builder.build();

            try {
                post.setEntity(entity);
               // HttpClient client2 = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();
                HttpResponse response = client.execute(post, localContext);
               // HttpResponse response = client.execute(post, localContext);
                System.out.println(response);
            } catch (Exception exc) {
                System.out.println(exc.getMessage());
            }
        } catch (Exception olu) {
            System.out.println("cos poszlo zle");
        }
    } catch (WebDriverException ex) {
        System.out.println("Wystąpił błąd logowania");
    }
}

private static void logIn(){
    System.out.println("Rozpoczęcie logowania");
    WebElement loginField = driver.findElement(By.xpath(TextFieldEnum.USER.getxPath()));
    WebElement passwordField = driver.findElement(By.xpath(TextFieldEnum.PASSWORD.getxPath()));

    WebElement button  = driver.findElement(By.xpath(ButtonEnum.ZALOGUJ.getxPath()));

    SeleniumTools.setTextFieldsValue(loginField, user);
    SeleniumTools.setTextFieldsValue(passwordField, password);
    SeleniumTools.clickViaJS(button, driver);
    System.out.println("Zakończono logowanie");
}

public static ClientCookie convertCookie(Cookie browserCookie) {
    BasicClientCookie cookie = new BasicClientCookie(browserCookie.getName(), browserCookie.getValue());
    String domain = browserCookie.getDomain();
    if (domain != null && domain.startsWith(".")) {
        // http client does not like domains starting with '.', it always removes it when it receives them
        domain = domain.substring(1);
    }
    cookie.setDomain(domain);
    cookie.setPath(browserCookie.getPath());
    cookie.setExpiryDate(browserCookie.getExpiry());
    cookie.setSecure(browserCookie.isSecure());
    if (browserCookie.isHttpOnly()) {
        cookie.setAttribute("httponly", "");
    }
    return cookie;
}

public static CookieStore copySeleniumCookies(Set<Cookie> browserCookies, CookieStore cookieStore) {
    for (Cookie browserCookie : browserCookies) {
        ClientCookie cookie = convertCookie(browserCookie);
        cookieStore.addCookie(cookie);
    }
    return  cookieStore;
}

【讨论】:

    猜你喜欢
    • 2016-11-11
    • 2012-11-24
    • 2016-06-29
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    相关资源
    最近更新 更多