skip to Main Content

I’m trying to send a byte array to the server through AJAX:

$.ajax({
  url: armd.scieldan.server + "/detachedSignFile/",
  timeout: 120000,
  type: "POST",
  data: byteArray,
  responseType: 'arraybuffer',
  success: function(response) {
    console.log("Sign: " + response);
  },
  error: function() {
    console.log("error");
  }
});

And trying to extract that array from httpExchange, but the content of requestBody is empty:

public void handle(HttpExchange httpExchange) throws IOException {
    httpExchange.getResponseHeaders().set("Content-Type", "text/plain");

    InputStream requestBody = httpExchange.getRequestBody();

    byte[] receivedBytes = IOUtils.toByteArray(requestBody);
}

enter image description here

Actually BufferedInputStream is contained inside the requestBody, but it is unreachable.

Any ideas how can I correctly pass the byte array through JSON to HttpExchange?

2

Answers


  1. Chosen as BEST ANSWER

    The problem was that I didn't notice that my initial AJAX request sent the "OPTIONS" HTTP method which means that I had to treat it as a preflight request. After adding some headers my server side code now looks like this:

    @Override
    public void handle(HttpExchange httpExchange) throws IOException {
        httpExchange.getResponseHeaders().add("Access-Control-Allow-Origin", "*");
        httpExchange.getResponseHeaders().add("Access-Control-Max-Age", "600");
        httpExchange.getResponseHeaders().add("Content-Type", "application/octet-stream");
        httpExchange.getResponseHeaders().add("Access-Control-Allow-Headers", "*");
    
        byte[] cms = null;
        int statusCode;
    
        if (httpExchange.getRequestMethod().equals("OPTIONS")) {
            OutputStream responseBody = httpExchange.getResponseBody();
            httpExchange.getResponseHeaders().add("Content-Type", "text/plain");
            httpExchange.getResponseHeaders().add("Access-Control-Allow-Headers", "*");
            httpExchange.sendResponseHeaders(204, 0);
            responseBody.flush();
            responseBody.close();
            return;
        }
        Map parameters = (Map) httpExchange.getAttribute("parameters");
        byte[] receivedBytes = IOUtils.toByteArray(parameters.get("data").toString());
       
        //other logic and response
    }
    

    Now after processing a request with the "OPTIONS" method, AJAX automatically send a proper "POST" request.


  2. If you are using AJAX on the client side and HTTP/REST on the server, it generally treats your content as string data unless you tell it otherwise and use special handling.

    The simplest way to improve what you have, which may work if your content is not too large and your performance needs are not too strict, is to base-64 encode the bytes and send that as the payload as text/plain (request content type). On the server, you can either read the entire input stream and decode or wrap the stream in a base-64 decoder.

    Another alternative is to send the data with a binary content type, such as application/octet-stream unless you have a specific file type. This way the network infrastructure from the browser/client to the server knows how to handle the bytes sent.

    What may be occurring is that the content type is not currently being specified explicitly and is defaulting to something like text/plain or application/json, then hitting an invalid sequence of bytes such as a null character when ASCII or another encoding is expected. This is resulting in your input stream processing being interrupted and input data lost, resulting in nothing reported to the server.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search