The XMLHTTP request and Chrome developer tools do not show matching information

I am currently downloading a file in chunks using XMLHttpRequest and the Range header. Everything is going smoothly, except for when I try to determine if I have downloaded the last chunk.

Here's a snapshot of the initial request and response for the first chunk. The Content-Length shows that it is 5 MB. However, upon copying the response body into a text editor, I noticed that there were 144 characters missing. This discrepancy occurs with every chunk downloaded.

The most peculiar part is the last chunk. The server responds by sending only ~2.9 MB instead of the full 5 MB, yet still correctly indicates this in the response headers.

Upon inspecting using Javascript, I discovered that Chrome was showing an additional 5 MB being downloaded beyond the file size, while Firefox displayed it correctly.

With the discrepancies between xhr.responseText.length and Content-Length, as well as conflicting information in the headers, I am at a loss on how to resolve this issue.

Update: After examining the raw HTTP request through telnet, it appears that the server is functioning properly. It seems like Chrome may be experiencing a bug. Should this issue be reported?

Answer №1

An issue arises when interpreting binary data as text. When the server responds with

Content-Type: application/octet-stream
, it does not specify the encoding explicitly. Consequently, the browser assumes UTF-8 encoding for the data. While most bytes (0 to 127) are interpreted as single characters in UTF-8, higher value bytes are often replaced by a replacement character. However, valid multi-byte UTF-8 sequences within your binary file will be combined into one character, causing discrepancies between the length of responseText and the actual number of bytes received from the server.

To address this issue, you can enforce a specific encoding using the request.overrideMimeType() method. For example, specifying ISO 8859-1 may ensure that each byte is treated as a single character:

request.overrideMimeType("application/octet-stream; charset=iso-8859-1");

Alternatively, storing the server response in an ArrayBuffer specifically designed for handling binary data would provide a more robust solution:

var request = new XMLHttpRequest();
request.open(...);
request.responseType = "arraybuffer";
request.send();

...

var array = new Uint8Array(request.response);
alert("First byte has value " + array[0]);
alert("Array length is " + array.length);

As per MDN, setting responseType = "arraybuffer" is supported in Chrome 10, Firefox 6, and Internet Explorer 10. Refer to Typed arrays for additional information.

Note: Firefox also supports

responseType = "moz-chunked-text"
and
responseType = "moz-chunked-arraybuffer"
from version 9 onwards for receiving data in chunks without relying on ranged requests. Whereas Chrome is prioritizing implementation of the Streams API instead of these options.

Edit: Chrome's possible misrepresentation of response headers was not replicated without sample code. The potential culprit could be found in function partial_data.cc:

// We are making multiple requests to complete the range requested by the user.
// Just assume that everything is fine and say that we are returning what was
// requested.
void PartialData::FixResponseHeaders(HttpResponseHeaders* headers,
                                     bool success) {
  if (truncated_)
    return;

  if (byte_range_.IsValid() && success) {
    headers->UpdateWithNewRange(byte_range_, resource_size_, !sparse_entry_);
    return;
  }

This code snippet alters the returned Content-Length and Content-Range headers based on request parameters, potentially leading to mismatches. If experiencing issues, consider clearing the cache or verifying the accuracy of the resource_size_ variable against the actual file size indicated by the server response.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Jquery to verify an ajax server connection

Currently, I'm in the process of developing a web application using JQuery. One challenge I have encountered is ensuring that the code has access to the server before proceeding with any further actions. Below is the function I am currently using: fun ...

The Material UI dialog box popped up against an unexpected gray backdrop

Currently, I am using Material UI in conjunction with React to create a dialog that appears when a button is tapped. This button is located within a table, which is displayed over a Paper component. The problem arises when I utilize the dialog with its def ...

What is the best way to pass the "getjson" capability from one function to another in a seamless manner?

Currently, I am dealing with a situation where a getjson call is used to retrieve a large amount of data. However, I find myself constantly having to check if the data is null or not. Here is an example: if (data.Height == "") { $(&ap ...

Ajax loaded scripts are unable to access global variables

Index.html <script> let bar = 1; </script> This html page is being loaded multiple times on the page using AJAX: article.html <script> if (bar === 1) { // perform a task } // Error: bar is not defined </script> Bar is a simple ...

Ensure that immutability is strictly enforced, or allow for partial immutability without the risk of silently failing

Is there a method to implement partial immutability on an object in a way that triggers an error if any attempt at mutation is made? For instance, consider let obj = {a: 1, b: 2}. I am interested in making obj.a and obj.b immutable while still allowing ad ...

The email form on this template is malfunctioning

I've recently started using a template to create a website and everything has been working perfectly... except for the fact that the email script variables are consistently empty. Here is the form: <form id="main-contact-form" name="contact-form" ...

What is the best way to add attachments to the clipboard in a Chrome extension?

One possible way to achieve this is by using the navigator.clipboard.write API, but keep in mind that this API is not available to background pages of Chrome extensions. A method I attempted involved creating a blob like this: let blobFinal = null; // ...

How can I use Three.JS TWEEN to animate object movement between two objects at a

I'm working on a game where an object moves towards other objects. new TWEEN.Tween( object.position ).to({ x: Math.position = pointX, z: Math.position.z = pointZ }).easing( TWEEN.Easing.Linear.None).start(); However, I've encountered a pr ...

The importance of displaying doughnut chart tooltips in Angular 5 console

Is there a way to consistently display tooltips for a doughnut chart? This code snippet might help: Chart.pluginService.register({ beforeRender: function(chart) { if (chart.config.options.showAllTooltips) { // create an array of tooltips // we ...

Retrieve the file path of the local system's home directory from the server

The server is up and running, I am looking to retrieve the file path of the local system in which the AWS server is operating using Node.js. ...

Unable to place value into an array following the invocation of a function in Angular 9

Within an array I established, I am encountering an undefined value when I use console.log. Take a look at my component.ts below: export class OrderExceptionReportComponent implements OnInit { public sessionData: ExceptionReportSessionData[] = []; n ...

Determine the 'source' attribute value of the image (img) with a dynamically changing Id

Below is the code snippet: <img id="simple_captcha-ad089ff4819" src="/simple_captcha?code=a35401d"> The id of the above img tag changes constantly with each new action. For example, the next id could be "simple_captcha-sfw454sdfs". Therefore, I n ...

Dynamically getting HTML and appending it to the body in AngularJS with MVC, allows for seamless binding to a

As someone transitioning from a jQuery background to learning AngularJS, I am facing challenges with what should be simple tasks. The particular issue I am struggling with involves dynamically adding HTML and binding it to a controller in a way that suits ...

The definition of Csrftoken is missing

The code I am currently using, as per the recommended documentation, is: function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); ...

Utilize Recurly's Node to generate a transaction with stored billing details

I need help creating a transaction using Recurly stored billing information. I am currently using the node-recurly module in my Node.js application. https://github.com/robrighter/node-recurly Below is the code snippet that I have written: recurly.transa ...

PhantomJS: Saving SVG for Future Use

I am attempting to save an SVG file from a sample testpage using PhantomJS. I have successfully navigated to the testpage, but I am unsure of how to locate and save the SVG element. Below is my current approach and where I am encountering difficulties. V ...

Sending both the minimum and maximum slider values to PHP using POST can be achieved by formatting the data correctly

I am attempting to transmit the minimum and maximum values to PHP using submit through a dual slider bar The static page makes a request to the server-side PHP code <?php include('server/server.php') ?> Below is the JavaScript code ...

Functions perfectly on Chrome, however, encountering issues on Internet Explorer

Why does the Navigation Bar work in Chrome but not in Internet Explorer? Any insights on this issue? The code functions properly in both Internet Explorer and Chrome when tested locally, but fails to load when inserted into my online website editor. Here ...

Incorporating Javascript into a <script> tag within PHP - a step-by-step guide

I am trying to integrate the following code into a PHP file: if (contains($current_url, $bad_urls_2)) { echo '<script> $('body :not(script,sup)').contents().filter(function() { return this.nodeType === 3; ...

The magnifying glass icon is missing from the autocomplete search feature

After creating an autocomplete search functionality that queries my mysql database, I encountered a slight issue. Here is the code snippet showcasing my implementation: <div class="search-bar"> <div class="ui-widget"> <input id="ski ...