I would like to get a rough estimate of the users' upload speed without getting direct permission. This is only to distinguish really slow connections from very fast ones so accuracy is not super important...
问题:
回答1:
Here's an implementation of this using XMLHttpRequest
expanding on @Yiğit Yener's idea.
Upload speed is dependent on two things: the user's connection speed and the server's connection speed. I made the assumption here that you want to test the speed between the user and your server. And with XMLHttpRequest
, that's really the only option because of the same-origin policy.
With upload speed, you don't need to return anything. You just need to POST
a large chunk of data to any page on your server. The easiest page to hit is the one you're already on. To do this you can leave the domain portion of the url out altogether in .open()
. POST
data is limited on some servers to two megabytes, so I used one to be safe. One is enough to get a decent reading.
To prevent the URL from being cached, I append a random number to the end.
url = '?cache=' + Math.floor( Math.random() * 10000 )
To prevent the POST
data from being gzipped, I use random data. The function allows you to pass the number of iterations you wish to check. Iterations are spaced out to every five seconds. The update
callback gets called each iteration with the speed of that check, and the moving average of all the checks. Use as many iterations as you wish to get your desired accuracy. If you just want a rough estimate, one iteration is enough.
It's called like this:
checkUploadSpeed( 10, function ( speed, average ) {
} );
Demos
You can try this code here.
Private Server
You can try this on ThinkingStiff's own server, which is probably the fastest out of these all.
Stack Snippet
function checkUploadSpeed( iterations, update ) {
var average = 0,
index = 0,
timer = window.setInterval( check, 5000 ); //check every 5 seconds
check();
function check() {
var xhr = new XMLHttpRequest(),
url = '?cache=' + Math.floor( Math.random() * 10000 ), //random number prevents url caching
data = getRandomString( 1 ), //1 meg POST size handled by all servers
startTime,
speed = 0;
xhr.onreadystatechange = function ( event ) {
if( xhr.readyState == 4 ) {
speed = Math.round( 1024 / ( ( new Date() - startTime ) / 1000 ) );
average == 0
? average = speed
: average = Math.round( ( average + speed ) / 2 );
update( speed, average );
index++;
if( index == iterations ) {
window.clearInterval( timer );
};
};
};
xhr.open( 'POST', url, true );
startTime = new Date();
xhr.send( data );
};
function getRandomString( sizeInMb ) {
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_+`-=[]\{}|;':,./<>?", //random data prevents gzip effect
iterations = sizeInMb * 1024 * 1024, //get byte count
result = '';
for( var index = 0; index < iterations; index++ ) {
result += chars.charAt( Math.floor( Math.random() * chars.length ) );
};
return result;
};
};
checkUploadSpeed( 10, function ( speed, average ) {
document.getElementById( 'speed' ).textContent = 'speed: ' + speed + 'kbs';
document.getElementById( 'average' ).textContent = 'average: ' + average + 'kbs';
} );
<div id="speed">speed: 0kbs</div>
<div id="average">average: 0kbs</div>
JSFiddle
JSFiddle servers where the demo is hosted are slower.
Click this button to go to the fiddle:
回答2:
You can make an asynchronous ajax request to a service which sends/returns large amount of data, and measure the time it takes the client to load. This of course is affected by the clients current network usage.
回答3:
One way to do this that comes to mind is to create an iframe
with a form
with a textarea
in it, fill the textarea
with a large number of random characters, and then programmatically submit the form. Have the submission response call out to the parent window to say when it completed, and measure the time from submission to completion. You might start with a relatively small payload (so it doesn't take forever on a slow connection) and, if that comes back very quickly, repeat with increasingly large payloads until you're happy with the result. The same sort of thing could be done with ajax, I suppose, not sure why I immediately thought in terms of an iframe
. See my other answer here on Stack Overflow, but think in terms of increasingly large form data instead of download data.
This will give you a very rough measure of upload speed.