繁体   English   中英

请求实体太大-Google Map Directions错误413

[英]Request entity too large - google map directions error 413

首先,我想说的是我对Google Maps Javascript API v3使用不太熟悉(我的唯一经历是最近3天)。 我设法显示了一个带有标记列表的DirectionsService ,并使用DirectionsService将它们连接起来,但是有时我的列表很大,并且出现以下错误:

Failed to load resource: the server responded with a status of 413 (Request Entity Too Large)

这是我的代码:

// List of all locations for device 
var locations = [];
// example: locations = [
//     {datetime: '2014/09/28 20:20', location: '41.99999 21.99999 30.0'},
//     ... {...} ... may be more than 200 entries for locations
//     {datetime: '2014/09/28 20:25', location: '41.99999 21.99999 30.0'}
// ]

var map;
var markers = [];
var bounds = new google.maps.LatLngBounds();
var pathPoints = [];
var infoWindow = new google.maps.InfoWindow();
var accuracy = new google.maps.Circle({
    fillColor: '#ff4080',
    fillOpacity: 0.5,
    strokeOpacity: 0,
    zIndex: 0
});
var path = new google.maps.Polyline(polyOptions);
var geocoder;
var directionsService = new google.maps.DirectionsService();
var directionsDisplay;
var polyOptions = {
    geodesic: true,
    strokeColor: '#28b8b8',
    strokeOpacity: 1.0,
    strokeWeight: 8,
    zIndex: 1
}
function showInfoWindow(marker, datetime, acc){
    geocoder = new google.maps.Geocoder();
    geocoder.geocode({
        'latLng': marker.getPosition()
    }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            if (results[1]) {
                infoWindow.close();
                var date = datetime.split(" ")[0];
                var time = datetime.split(" ")[1];
                var content = '<div class="infowindow">'
                        + results[1].formatted_address.trim() + '<br />'
                        + 'Date: ' + date + '<br />'
                        + 'Time: ' + time + '<br />'
                        + 'Accuracy: ' + acc + 'm'
                        + '</div>';
                infoWindow.setContent(content);
                infoWindow.open(map, marker);
                accuracy.setMap(null);
                accuracy.setMap(map);
                accuracy.setCenter(marker.getPosition());
                accuracy.setRadius(acc/1.6);
            } else {
                // alert('No results found');
            }
        } else {
            alert('Geocoder failed due to: ' + status);
        }
    });
}
function addMultiMarker(latLng, num, datetime, acc){
    // Create marker at provided location
    var marker = new google.maps.Marker({
        position: latLng,
        map: map,
        icon: image_circle,
        title: 'Location #' + num,
        zIndex: num + 1
    });
    // On marker click center it inside map and show infoWindow
    google.maps.event.addListener(marker, 'click', function() {
        map.panTo(marker.getPosition());
        showInfoWindow(marker, datetime, acc);
    });
    return marker;
}
function showRoute() {
    var rendererOptions = {
        draggable: false,
        hideRouteList: true,
        suppressMarkers: true,
        infoWindow: infoWindow,
        polylineOptions: polyOptions,
        map: map
    };
    directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
    var len = markers.length;
    var start = markers[0].getPosition();
    var end = markers[len - 1].getPosition();
    new google.maps.event.trigger(markers[len - 1], 'click');
    var wayPts = [];
    for(var i = 1; i < len - 1; i++){
        wayPts.push({
            location: markers[i].getPosition(),
            stopover: true
        });
    }
    var request = {
        origin: start,
        destination: end,
        waypoints: wayPts,
        optimizeWaypoints: true,
        travelMode: google.maps.TravelMode.DRIVING
    };
    directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            directionsDisplay.setDirections(response);
        }
    });
}
function showMapPeriod(periodStart, periodEnd){
    // Simple map options
    var mapOptions = {
        zoom: 15,
        center: new google.maps.LatLng(41, 21),
        mapTypeId : google.maps.MapTypeId.ROADMAP,
        mapTypeControl: true,
        mapTypeControlOptions: {
            style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
            position: google.maps.ControlPosition.TOP_RIGHT
        },
        zoomControl: true,
        zoomControlOptions: {
            style: google.maps.ZoomControlStyle.LARGE,
            position: google.maps.ControlPosition.LEFT_CENTER
        },
        panControl: false,
        streetViewControl: false
    };
    $("#map").html("");
    // Create and show map
    openMapContainer(); // just a function that shows the map <div> element
    map = new google.maps.Map(document.getElementById('map'), mapOptions);
    // Create and display markers
    bounds = new google.maps.LatLngBounds();
    markers = [];
    var len = 0;
    for(var i = periodStart; i <= periodEnd; i++, len++){
        var loc_vals = locations[i].location.trim().split(" ");
        var lat = parseFloat(loc_vals[0]);
        var lng = parseFloat(loc_vals[1]);
        var acc = parseFloat(loc_vals[2]);
        // Create marker at provided location
        var datetime = locations[i].datetime;
        var latLng = new google.maps.LatLng(lat, lng);
        markers[len] = addMultiMarker(latLng, len+1, datetime, acc);
        bounds.extend(latLng);
    }
    showRoute();
    map.fitBounds(bounds);
}

好吧,我的代码部分起作用,如果有人可以帮助我消除问题,我将非常感激。 为了更好地解释它,我需要某种解决方案来请求具有很多(200+)航路点的Directions ,或者通过某种方式来连接道路位置(我并不需要方向,但是我不想连接用简单的Polyline定位位置)。

编辑: 在这里我提供了一个简单的演示,以查看问题只是在line 15注释。

由于没有人能够帮助我解决问题,因此我必须自己解决问题。 我正在回答自己的问题,因为这对很多人来说都是个问题,并且在网络上解释得还不够,因此这可能会对有类似问题的开发人员有所帮助。

无论如何,让我们说清楚。 该错误是由于OxyDesign建议的Google限制而引发的 ,错误为:

  • google.maps.DirectionsResult.MAX_WAYPOINTS_EXCEEDED这是因为我发送了一个包含起点目的地和8个以上(Google限制) 航路点的请求。

我很容易解决的问题(我只是将数组分成10个点,将一个请求的最后一个点作为下一个请求的第一个点),但是随后出现另一个错误:

  • google.maps.DirectionsResult.OVER_QUERY_LIMIT这是因为我尝试每秒发送10个以上的请求(同样是Google的限制)。

需要更多的实验,搜索和测试才能解决,但是我解决了。

现在,这是对我有用的代码(至少在发布时,直到Google进行了一些更改):

// list of randomly generated locations (max 288)
var locations = [];
for(var i=0; i<288; i++){
    locations[i] = {
        datetime: '2014/10/01 12:10',
        location: (51 + Math.random()) +
        ' ' + (-0.5 + Math.random()) + ' 30.0'
    };
}
// Marker images
var image_pin = new google.maps.MarkerImage(
    'http://stedkomerc.com.mk/gpslocator/images/mPin.svg',  
    new google.maps.Size(25, 41),  // size
    new google.maps.Point(0, 0),   // origin, top-left corner
    new google.maps.Point(12, 40)  // anchor
);
var image_circle = new google.maps.MarkerImage(
    'http://stedkomerc.com.mk/gpslocator/images/mCircle.svg',
    new google.maps.Size(19, 19),  // size
    new google.maps.Point(0, 0),   // origin, top-left corner
    new google.maps.Point(9, 9)    // anchor
);
// Variables
var map;
var bounds = new google.maps.LatLngBounds();
var markers = [];
var pathPoints = [];
var geocoder;
var infoWindow = new google.maps.InfoWindow();
var accuracy = new google.maps.Circle({
    fillColor: '#ff4080',
    fillOpacity: 0.4,
    strokeOpacity: 0,
    zIndex: 0
});
var polyOptions = {
    geodesic: true,
    strokeColor: '#28b8b8',
    strokeOpacity: 1.0,
    strokeWeight: 8,
    zIndex: 1
};
var path = new google.maps.Polyline(polyOptions);
var directionsService = new google.maps.DirectionsService();
var directions = [];
var rendererOptions = {
    draggable: false,
    hideRouteList: true,
    suppressMarkers: true,
    preserveViewport: true,
    infoWindow: infoWindow,
    polylineOptions: polyOptions
};
var requests = [];
var MAX_POINTS_PER_REQUEST = 10; // 8*waypts Google limit + start + end
var MAX_REQUESTS_PER_SECOND = 10; // Google limit
// functions
function showInfoWindow(marker, datetime, acc){
    geocoder = new google.maps.Geocoder();
    geocoder.geocode({
        'latLng': marker.getPosition()
    }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            if (results[1]) {
                infoWindow.close();
                var date = datetime.split(" ")[0];
                var time = datetime.split(" ")[1];
                var content = '<div class="infowindow">' +
                    results[1].formatted_address.trim() + '<br />' +
                    'Date: ' + date + '<br />' +
                    'Time: ' + time + '<br />' +
                    'Accuracy: ' + acc + 'm' +
                    '</div>';
                infoWindow.setContent(content);
                infoWindow.open(map, marker);
                accuracy.setMap(null);
                accuracy.setMap(map);
                accuracy.setCenter(marker.getPosition());
                accuracy.setRadius(acc);
            }
        } else {
            console.log('Geocoder failed due to: ' + status);
        }
    });
}
function addMultiMarker(latLng, num, datetime, acc){
    // Create marker at provided location
    var marker = new google.maps.Marker({
        position: latLng,
        map: map,
        icon: image_circle,
        title: 'Location #' + num,
        zIndex: num + 1
    });
    // On marker click center it inside map and show infoWindow
    google.maps.event.addListener(marker, 'click', function() {
        //map.panTo(marker.getPosition());
        showInfoWindow(marker, datetime, acc);
    });
    return marker;
}
function connectMarkersPolyline(mrkrs){
    path.setMap(map);
    pathPoints = path.getPath();
    len = mrkrs.length;
    for(var i = 0; i < len; i++){
        pathPoints.push(mrkrs[i].getPosition());
    }
}
function connectMarkersRoute(mrkrs, part, maxParts){
    var directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
    directionsDisplay.setMap(map);
    var len = mrkrs.length;
    var start = mrkrs[0].getPosition();
    var end = mrkrs[len - 1].getPosition();
    var wayPts = [];
    for(var i = 1; i < len - 1; i++){
        wayPts.push({
            location: mrkrs[i].getPosition(),
            stopover: true
        });
    }
    var request = {
        origin: start,
        destination: end,
        waypoints: wayPts,
        optimizeWaypoints: false,
        travelMode: google.maps.TravelMode.DRIVING,
        unitSystem: google.maps.UnitSystem.METRIC
    };
    directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            // request status OK, display route
            directionsDisplay.setDirections(response);
            // save it in array in case we want to remove it later
            directions.push(directionsDisplay);
            // if not last chunk, send next chunk after 100ms
            // 1 request per 100ms => 10 requests per 1s
            if(part+1 < maxParts)
                setTimeout(connectMarkersRoute(requests[part+1], part+1, maxParts), 100);
            else showLastMarker();
        } else if (status == google.maps.DirectionsStatus.OVER_QUERY_LIMIT) {
            // if we get error, send same request after bigger delay (120ms)
            setTimeout(connectMarkersRoute(requests[part], part, maxParts), 120);
        } else {
            // if all fails, connect with simple polyline
            console.log('Directions failed due to: ' + status);
            connectMarkersPolyline(mrkrs);
        }
    });
}
function connectMarkers(markers){
    path.setMap(null);
    path.setPath([]);
    directions = [];
    requests = [];
    var len = markers.length;
    console.log('connecting ' + len + ' markers');
    var i, j;
    // split markers array into chunks of 10 (start + waypts + end)
    for(i=0; i<len; i+=MAX_POINTS_PER_REQUEST-1){
        if(i<len-1)
            requests.push(markers.slice(i, i+MAX_POINTS_PER_REQUEST));
    }
    // send first chunk to connectMarkersRoute()
    connectMarkersRoute(requests[0], 0, requests.length);
}
function showMapPeriod(periodStart, periodEnd){
    // Map options
    var mapOptions = {
        zoom: 16,
        center: new google.maps.LatLng(41.995922, 21.431465),
        mapTypeId : google.maps.MapTypeId.ROADMAP,
        mapTypeControl: true,
        mapTypeControlOptions: {
            style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
            position: google.maps.ControlPosition.TOP_RIGHT
        },
        zoomControl: true,
        zoomControlOptions: {
            style: google.maps.ZoomControlStyle.LARGE,
            position: google.maps.ControlPosition.LEFT_CENTER
        },
        panControl: false,
        streetViewControl: false
    };
    $("#map").html("");
    //openMapContainer();
    // Create and show map
    map = new google.maps.Map(document.getElementById('map'), mapOptions);
    // Create and display markers
    bounds = new google.maps.LatLngBounds();
    markers = [];
    var len = 0;
    for(var i = periodStart; i <= periodEnd; i++, len++){
        var loc_vals = locations[i].location.trim().split(" ");
        var lat = parseFloat(loc_vals[0]);
        var lng = parseFloat(loc_vals[1]);
        var acc = parseFloat(loc_vals[2]);
        // Create marker at provided location
        var datetime = locations[i].datetime;
        var latLng = new google.maps.LatLng(lat, lng);
        markers[len] = addMultiMarker(latLng, len+1, datetime, acc);
        bounds.extend(latLng);
    }
    connectMarkers(markers);
    map.fitBounds(bounds);
    if(map.getZoom() > 16) map.setZoom(16);  
}
function showLastMarker(){
    new google.maps.event.trigger(markers[markers.length - 1], 'click');  
}
// show map
showMapPeriod(1, 280);
// --------

正如你所看到的,我所做的唯一真正的变化是showRoute()函数成为connectMarkers()结合connectMarkersRoute()connectMarkersPolyline()是处理这两个错误。

工作示例可以在这里看到。 加载所有路由块花费一些时间,但至少可以正常工作。 希望这也会对其他人有所帮助。

请注意,Google每天还有2500个Directions请求的限制,因此请注意。 话虽如此,这个答案甚至适用于超过200个地点的更大请求,我已经在1250个地点进行了测试,并且有效。

这项服务的Gmaps Waypoints似乎有一个局限性(我尝试过823 ,直到39时才起作用,然后40才失效),除了折线以外,没有其他方法可以实现,但您不希望这样做我认为没有可行的解决方案...

暂无
暂无

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

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