Content-Length header is not getting in Android 2.3 above browser - php

I am having an hybrib application in that in that a simple php page will open which contents some link of files, and from my android wrapper i have implemented the download functionality of file.
So for user convenience i am showing the length and progress of download while the file is downloading for that my application server has set a content-length header to pass the size on device, but the problem I am facing is surprising.
The file length is working fine in Android 2.2. I am getting the content header correctlt but in Android 2.3 above I am getting the content length for smaller files but for the larger file I am not even getting the Header Field.
con.getHeaderField("content-length");
returning me null in case of Android 2.3 above.
So is there any limitation of size for the User Agent above 2.3 because if it is working fine in 2.2 means there is no problem at server end it is the problem only on device user agent.
Update
I have tried it with different size of files and it is working fine till 60KB in Android 2.3 above as well.

It sounds like the client may be chunking the file. Check for the presence of the following header:
Transfer-Encoding: chunked
If that exists, the request is chunked and you will not get a Content-Length header.
See http://en.wikipedia.org/wiki/Chunked_transfer_encoding for more details.

Related

Apache and Content-Range

I am trying to implement support for Content-Range in PHP-generated files. When a browser sends Range request my script gives correct bytes and it works well.
But while testing how Content-Range looks when downloading a PDF from Apache server I realized the first request from a web browser to my server does not contain Range header but somehow server still doesn't return full file and only 32 kB.
On this screenshot you can see that Firefox sends 5 requests to Apache for my_pdf.pdf and Apache each time responds with 32-192 kB. The whole PDF is 28 MB. Requests 2-5 do contain Range request. But the first request- highlighted does not. You can see on the right that Content-Length is 28 MB but that Apache returned only 32 kB.
So my question is- how did Apache know to return only 32 kB and not the whole 28 MB PDF file?
So my question is- how did Apache know to return only 32 kB and not the whole 28 MB PDF file?
It didn't. If you look at the Content-Length header in the response, it shows the full file size of 29.3 million bytes.
The client probably closed the connection without reading the entire response.
Answer posted by #duskwuff is correct- Firefox terminates the transfer of the first requests once it gets enough to process the PDF.
Below is just a few details I discovered.
Firefox will terminate if your scripts returns these headers:
Accept-Ranges: bytes
Content-Length: 29293315
You can (but don't have to) also return this header:
header("Content-Range: bytes 0-29293314/29293315");
However by default Apache tries to compress whatever PHP returns and then adds this header:
Transfer-Encoding: chunked
And when Firefox (and Chrome) see this they won't close the connection. So I just disabled Apache compression and everything works. Now Firefox just does a few requests, get bits of PDF instead of the whole file and renders first page just fine (because it didn't need whole PDF to render just the first page).

Download counter function inaccurate

We're using a normal PHP download script (with headers etc) to serve files to users.
The issue however is that with some browsers and large downloads the download script is requested multiple times. NGINX logs show the requests with a 206 status code, (suggesting chunked streaming?) which is strange because we don't serve any streamable content?
Regardless, this means the download script is requested multiple times and thus the MySQL function of +1'ing the download counter for the file is run multiple times per download.
We tried using sessions, but seeing as the download is severed from an external server + domain we have no way to clear said sessions after they're set.
We're using Laravel with NGINX + MySQL, any help would be appreciated. Thanks!
Looking at the spec and the headers for the request which would ultimately result in a 206 response, there was one header which struck out which looks like it would be perfect.
The header in question is the Content-Range header which could look like the following:
Content-Range: bytes 21010-47021/47022
What this is saying is it wants to grab bytes 21010-47021 out of 47022 bytes. All you should need to be worried about is the first number here and if it's 0 or not. If the header was set and the first number is 0, you can assume it's just beginning the download and you should increment the counter.

I get many 206 partial content

I have a client application that sends the data to a php file (hosted on Apache). Usually this works without any problem. On a client site I get 206 partial content every time the client app sends data.
The data size is 10 - 30 kB so it is not huge.
If you have any suggestion - like changing Apache settings .. or something similar I would appreciate it.
Thanks.
Its not an issue. Any 2xx code means "Success". You can view details # Why does Firebug show a "206 Partial Content" response on a video loading request?

Setting header for notify file content changed. PHP, Twilio

I'm working on a twilio project with PHP which will be playing back a frequently changing audio file.
Twilio's TwiML Voice documentation states to:
make sure your web server is sending the proper headers to inform us
that the contents of the file have changed
Which headers are these and how do I set them in PHP.
Which headers are these?
This is how caching works on Twilio
Twilio requests a .mp3 from your server using a GET request. Your
server sends back a 200 OK, and also sends back an E-Tag header.
Twilio will save the E-Tag header, as well as the mp3 file, in its
database.
The next time Twilio sends a GET request to that URL, it will send
along the E-Tag header (it should look like "If-None-Match"). If the
file has not changed since the last time Twilio accesses it, your
server will send back a 304 Not Modified header. Crucially, it will
not send the mp3 file data. Twilio will use the mp3 file it has
stored in its database. It's much faster for Twilio to read the mp3
file from its database than it is for your server to send it (and it
also saves your server bandwidth).
If you change the content of the mp3 that is being served at the URL,
and Twilio makes a GET request to the URL, then your server will send
back a 200 OK, with a new E-Tag. Twilio will download the file from
your server, and cache it.
How do I set them in PHP?
header("ETag: \"uniqueID\");
When sending a file, web server attaches ID of the file in header called ETag. When requesting file, browser checks if the file was already downloaded. If cached file is found, server sends the ID with the file request to server. Server checks if the IDs match and if they do, sends back header("HTTP/1.1 304 Not Modified"); else Server sends the file normally.
One easy way to check is by adding some fake key-value pairs to the end of the URL, like http://yoururl.com/play.mp3?key=somevalue. Your website should still serve the same mp3 as it would if you loaded example.com/test.mp3, but to Twilio it will appear to be a new URL (uncached).
Twilio uses Squid to cache MP3. You can control how long an item is cached using the cache control header.
cache-control: max-age=3600
http://wiki.squid-cache.org/SquidFaq/InnerWorkings#How_does_Squid_decide_when_to_refresh_a_cached_object.3F

How to obtain size of served HTTP response in PHP

In a PHP shutdown function, I want to know the size of the HTTP response that's been received by the client.
I'd like to register a shutdown function and verify the size of the HTTP response received by the client with the size of the file which was read. This would let me flag cases where the response was incomplete.
Background: We're seeing reports of damaged (incomplete) file downloads using Ubercart uc_file.
http://api.ubercart.org/api/function/_uc_file_download_transfer/2 is the function serving the file. It already checks that the complete file has been read before logging the download, but it doesn't check if the client was still connected when the file is fully served.
I don't know how to obtain the size of generated content, but the reason why your clients are experiencing incomplete downloads could be that you don't specify the correct Content-Length header before sending the file. Standards-compliant browsers will not save the file if it's size turns out to be less than the Content-Length declared in HTTP response.

Categories