简体   繁体   English

通过 Java 中的 http 请求发送 base64 图像错过了一些字符

[英]Sending base64 image via http request in Java miss up some chars

I've been trying to send a base64 image using java to NodeJS API, after working and searching for hours I could not know what might cause the following problem, the problem as following:我一直在尝试使用java将 base64 图像发送到NodeJS API,经过几个小时的工作和搜索,我不知道是什么可能导致以下问题,

After logging the base64 image in nodejs I see all + chars replaced by space在 nodejs 中记录 base64 图像后,我看到所有+字符都被space替换

Here's a part of the original base64 in Java这里是Java中原Java的一部分

f8A0NH2qH+/+hooouAfaof7/wCho+1Q/

and here's is a part of the received image in NodeJS这是NodeJS中接收到的图像的一部分

f8A0NH2qH / hooouAfaof7/wCho 1Q/

I've tried to send an image via POSTMAN and no problem at all.我尝试通过POSTMAN发送图像,完全没有问题。

All steps as following:所有步骤如下:

1- I am converting an image to base64 using the following snippet 1-我正在使用以下代码段将图像转换为 base64

public static String imgToBase64String(final RenderedImage img, final String formatName) {
        final ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            ImageIO.write(img, formatName, Base64.getEncoder().wrap(os));
            return os.toString(StandardCharsets.ISO_8859_1.name());
        } catch (final IOException ioe) {
            throw new UncheckedIOException(ioe);
        }
    }

    public static BufferedImage base64StringToImg(final String base64String) {
        try {
            return ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(base64String)));
        } catch (final IOException ioe) {
            throw new UncheckedIOException(ioe);
        }
    }

And to take screenshot并截图

    final Robot robot = new Robot();
    final Rectangle r = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
    final BufferedImage bi = robot.createScreenCapture(r);
    final String base64String = Base64Converter.imgToBase64String(bi, "jpg");

2- I am using Gson library to stringify object 2-我正在使用Gson库对 object 进行字符串化

3- I am using bodyParser in NodeJS 3-我在NodeJS中使用bodyParser

4- Sending HTTP request as: 4-发送HTTP请求为:

public static void sendPOST(String image) throws Exception {
        String POST_PARAMS = "screenShotData";
        URL obj = new URL(POST_URL);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("POST");
        con.setConnectTimeout(5000); // 5 seconds
        con.setReadTimeout(5000); // 5 seconds

        Gson gson = new Gson();
        Http.ScreenShot screenShot = new ScreenShot(); // This is just a class with a string property
        screenShot.setImage(image);
        POST_PARAMS += gson.toJsonTree(screenShot).getAsJsonObject();


        con.setDoOutput(true);
        OutputStream os = con.getOutputStream();
        byte[] outputBytesArray = POST_PARAMS.getBytes();
        os.write(outputBytesArray);
        os.flush();
        os.close();


        int responseCode = con.getResponseCode();
        System.out.println("POST Response Code :: " + responseCode);

        if (responseCode == HttpURLConnection.HTTP_OK) { //success
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            Object responseObject = gson.fromJson(response.toString(), Object.class);
            System.out.println("Res: " + responseObject);
        } else {
            System.out.println(con.getResponseMessage());
        }
    }

In URL encoded text, the + character means a space character.在 URL 编码文本中, +字符表示空格字符。 For example,例如,

https://example.com/?s=nodejs+bodyparser

sends the s parameter with the value发送带有值的s参数

nodejs bodyparser 

(notice the space). (注意空格)。

When you do an ordinary form post (the kind browsers do) you use the application/x-www-form-urlencoded data type, meaning the payload of your POST operation looks like a query string.当你做一个普通的表单发布(浏览器做的那种)时,你使用application/x-www-form-urlencoded数据类型,这意味着你的 POST 操作的有效负载看起来像一个查询字符串。 I think you are passing a JSON object as a text string without url-encoding it.我认为您将 JSON object 作为文本字符串传递,而没有对其进行 url 编码。

You probably want to use the application/json data type instead.您可能想改用application/json数据类型。 nodejs's body parser detects, from your Content-type header, that it's JSON and parses it correctly. nodejs 的正文解析器从您的内容类型 header 中检测到它是 JSON 并正确解析它。

Try this.尝试这个。 (not debugged, sorry.) (未调试,抱歉。)

    string payload = gson.toJsonTree(screenShot).getAsJsonObject();
    byte[] outputBytesArray = payload.getBytes();

    con.setRequestProperty("Content-Type", "application/json");
    con.setDoOutput(true);
    OutputStream os = con.getOutputStream();
    os.write(outputBytesArray);
    os.flush();
    os.close();

You forgot to close the wrapped Base64 encoder stream.您忘记关闭包装好的 Base64 编码器 stream。 Only if you close it the end of the base64 encoded data can be written:只有关闭它,base64 编码数据的末尾才能写入:

public static String imgToBase64String(final RenderedImage img, final String formatName) {
    final ByteArrayOutputStream os = new ByteArrayOutputStream();
    try {
        try (OutputStream wrapped = Base64.getEncoder().wrap(os)) {
            ImageIO.write(img, formatName, wrapped);
        }
        return os.toString(StandardCharsets.ISO_8859_1.name());
    } catch (final IOException ioe) {
        throw new UncheckedIOException(ioe);
    }
}

I had faced this issue, but I had no authority to change in class or something else.我遇到过这个问题,但我无权更改 class 或其他内容。 I had just simply replaced space with +, in most of the cases it was working.我只是简单地用 + 替换了空格,在大多数情况下它都有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM