it-swarm-vi.tech

Làm cách nào để có được tiến bộ từ XMLHttpRequest

Có thể có được tiến trình của XMLHttpRequest (byte được tải lên, byte được tải xuống) không?

Điều này sẽ hữu ích để hiển thị một thanh tiến trình khi người dùng đang tải lên một tệp lớn. API tiêu chuẩn dường như không hỗ trợ nó, nhưng có lẽ có một số tiện ích mở rộng không chuẩn trong bất kỳ trình duyệt nào ngoài đó? Rốt cuộc, nó có vẻ như là một tính năng khá rõ ràng, vì khách hàng biết có bao nhiêu byte được tải lên/tải xuống.

lưu ý: Tôi biết về giải pháp thay thế "thăm dò máy chủ để tiến bộ" (đó là những gì tôi đang làm ngay bây giờ). vấn đề chính với điều này (ngoài mã phía máy chủ phức tạp) là thông thường, trong khi tải lên một tệp lớn, kết nối của người dùng hoàn toàn bị ngắt, bởi vì hầu hết các ISP cung cấp ngược dòng kém. Vì vậy, thực hiện các yêu cầu bổ sung không đáp ứng như tôi mong đợi. Tôi đã hy vọng sẽ có một cách (có thể là không chuẩn) để có được thông tin này, mà trình duyệt có mọi lúc.

130
Pete

Đối với các byte được tải lên, nó khá dễ dàng. Chỉ cần theo dõi sự kiện xhr.upload.onprogress. Trình duyệt biết kích thước của các tệp mà nó phải tải lên và kích thước của dữ liệu được tải lên, vì vậy nó có thể cung cấp thông tin tiến trình.

Đối với các byte được tải xuống (khi nhận thông tin bằng xhr.responseText), sẽ khó khăn hơn một chút, vì trình duyệt không biết có bao nhiêu byte sẽ được gửi trong yêu cầu máy chủ. Điều duy nhất mà trình duyệt biết trong trường hợp này là kích thước của byte mà nó đang nhận.

Có một giải pháp cho vấn đề này, nó đủ để đặt tiêu đề Content-Length trên tập lệnh máy chủ, để có được tổng kích thước của byte mà trình duyệt sẽ nhận được.

Để biết thêm, hãy truy cập https://developer.mozilla.org/en/Using_XMLHttpRequest .

Ví dụ: Tập lệnh máy chủ của tôi đọc tệp Zip (mất 5 giây):

$filesize=filesize('test.Zip');

header("Content-Length: " . $filesize); // set header length
// if the headers is not set then the evt.loaded will be 0
readfile('test.Zip');
exit 0;

Bây giờ tôi có thể theo dõi quá trình tải xuống tập lệnh máy chủ, vì tôi biết tổng chiều dài của nó:

function updateProgress(evt) 
{
   if (evt.lengthComputable) 
   {  // evt.loaded the bytes the browser received
      // evt.total the total bytes set by the header
      // jQuery UI progress bar to show the progress on screen
     var percentComplete = (evt.loaded / evt.total) * 100;  
     $('#progressbar').progressbar( "option", "value", percentComplete );
   } 
}   
function sendreq(evt) 
{  
    var req = new XMLHttpRequest(); 
    $('#progressbar').progressbar();    
    req.onprogress = updateProgress;
    req.open('GET', 'test.php', true);  
    req.onreadystatechange = function (aEvt) {  
        if (req.readyState == 4) 
        {  
             //run any callback here
        }  
    };  
    req.send(); 
}
134
albanx
9
Markus Peröbner

Có một cuộc thảo luận thú vị về Chỉ báo tiến độ cho mẫu AJAX tại đây:

http://ajaxpotypes.org/ProTHER_Indicator

Một trong những cách tiếp cận hứa hẹn nhất dường như là mở một kênh liên lạc thứ hai trở lại máy chủ để hỏi xem có bao nhiêu việc chuyển tiền đã được hoàn thành.

8
Sean McMains
7
Maciej Łebkowski

Đối với tổng số đã tải lên, dường như không có cách nào để xử lý việc đó, nhưng có một cái gì đó tương tự với những gì bạn muốn tải xuống. Khi readyState là 3, bạn có thể định kỳ truy vấn answerText để tải tất cả nội dung được tải xuống dưới dạng Chuỗi (điều này không hoạt động trong IE), cho đến khi tất cả nội dung có sẵn tại thời điểm nó sẽ chuyển sang readyState 4. Tổng cộng byte được tải xuống tại bất kỳ thời điểm nào sẽ bằng tổng số byte trong chuỗi được lưu trữ trong answerText.

Đối với cách tiếp cận toàn bộ hoặc không có gì cho câu hỏi tải lên, vì bạn phải truyền một chuỗi để tải lên (và có thể xác định tổng số byte đó), tổng số byte được gửi cho readyState 0 và 1 sẽ là 0 và tổng số cho readyState 2 sẽ là tổng số byte trong chuỗi bạn đã truyền vào. Tổng số byte cả được gửi và nhận trong readyState 3 và 4 sẽ là tổng số byte trong chuỗi gốc cộng với tổng số byte trong responsText.

5
Orclev
<!DOCTYPE html>
<html>
<body>
<p id="demo">result</p>
<button type="button" onclick="get_post_ajax();">Change Content</button>
<script type="text/javascript">
        function update_progress(e)
        {
          if (e.lengthComputable)
          {
            var percentage = Math.round((e.loaded/e.total)*100);
            console.log("percent " + percentage + '%' );
          }
          else 
          {
                console.log("Unable to compute progress information since the total size is unknown");
          }
        }
        function transfer_complete(e){console.log("The transfer is complete.");}
        function transfer_failed(e){console.log("An error occurred while transferring the file.");}
        function transfer_canceled(e){console.log("The transfer has been canceled by the user.");}
        function get_post_ajax()
        {
                var xhttp;
                if (window.XMLHttpRequest){xhttp = new XMLHttpRequest();}//code for modern browsers} 
                else{xhttp = new ActiveXObject("Microsoft.XMLHTTP");}// code for IE6, IE5               
                xhttp.onprogress = update_progress;
                xhttp.addEventListener("load", transfer_complete, false);
                xhttp.addEventListener("error", transfer_failed, false);
                xhttp.addEventListener("abort", transfer_canceled, false);              
                xhttp.onreadystatechange = function()
                {
                if (xhttp.readyState == 4 && xhttp.status == 200)
                {
                        document.getElementById("demo").innerHTML = xhttp.responseText;
                }
                };
          xhttp.open("GET", "http://it-tu.com/ajax_test.php", true);
          xhttp.send();
        }
</script>
</body>
</html>

Result

3
Forums Lover

Nếu bạn có quyền truy cập vào cài đặt Apache của mình và tin tưởng mã của bên thứ ba, bạn có thể sử dụng mô đun tiến trình tải lên của Apache (nếu bạn sử dụng Apache; cũng có một mô đun tiến trình tải lên nginx ).

Mặt khác, bạn phải viết một tập lệnh mà bạn có thể thoát ra khỏi băng tần để yêu cầu trạng thái của tệp (ví dụ: kiểm tra kích thước tệp của tệp tmp).

Có một số công việc đang diễn ra trong firefox 3 Tôi tin rằng sẽ thêm hỗ trợ tiến trình tải lên cho trình duyệt, nhưng điều đó sẽ không được đưa vào tất cả các trình duyệt và được áp dụng rộng rãi trong một thời gian (đáng tiếc hơn).

2
Aeon