2016-12-08 16 views
11

Tôi đang làm việc trên một chức năng sẽ ghi dữ liệu vào máy chủ từ xa theo các khối sử dụng API của bên thứ ba. Thông qua một số trợ giúp về Stack Overflow, tôi đã có thể thực hiện điều này, nơi nó hiện đang hoạt động như mong đợi. Vấn đề là tôi chỉ có thể nhận được một đoạn 16kb duy nhất để viết vì tôi sẽ cần phải tạm ứng pos nơi các byte tiếp theo được ghi vào.Nhận Vị trí Byte trong Vòng Tải lên

Ghi ban đầu bắt đầu từ 0 một cách dễ dàng đủ. Do sự không quen thuộc của tôi với điều này mặc dù, tôi không chắc chắn nếu pos tiếp theo chỉ nên là 16 hoặc những gì. Nếu nó giúp, cuộc gọi API writeFileChunk() có 3 tham số, filepath (str), pos (int64) và dữ liệu (chuỗi được mã hóa base64).

reader.onload = function(evt) 
    { 
     // Get SERVER_ID from URL 
     var server_id = getUrlParameter('id'); 

     $("#upload_status").text('Uploading File...'); 
     $("#upload_progress").progressbar('value', 0); 

     var chunkSize = 16<<10; 
     var buffer = evt.target.result; 
     var fileSize = buffer.byteLength; 
     var segments = Math.ceil(fileSize/chunkSize); // How many segments do we need to divide into for upload 
     var count = 0; 

     // start the file upload 
     (function upload() 
     { 
      var segSize = Math.min(chunkSize, fileSize - count * chunkSize); 

      if (segSize > 0) 
      { 
       $("#upload_progress").progressbar('value', (count/segments)); 

       var chunk = new Uint8Array(buffer, count++ * chunkSize, segSize); // get a chunk 
       var chunkEncoded = btoa(String.fromCharCode.apply(null, chunk)); 

       // Send Chunk data to server 
       $.ajax({ 
        type: "POST", 
        url: "filemanagerHandler.php", 
        data: { 'action': 'writeFileChunk', 'server_id': server_id, 'filepath': filepath, 'pos': 0, 'chunk': chunkEncoded }, 
        dataType: 'json', 
        success: function(data) 
        { 
         console.log(data); 
         setTimeout(upload, 100); 
        }, 
        error: function(XMLHttpRequest, textStatus, errorThrown) 
        { 
         alert("Status: " + textStatus); alert("Error: " + errorThrown); alert("Message: " + XMLHttpRequest.responseText); 
        } 
       }); 
      } 
      else 
      { 
       $("#upload_status").text('Finished!'); 
       $("#upload_progress").progressbar('value', 100); 

       getDirectoryListing(curDirectory); 
      } 
     })() 
    }; 
+1

là gì mà API bên thứ 3, và không tài liệu không đề cập đến điều này? // Giả sử rằng nó có thể thực sự chỉ là vị trí byte có vẻ là một dự đoán đủ công bằng - vậy bạn đã nhận được kết quả gì khi bạn thử điều đó? – CBroe

+0

Nếu api bên thứ 3 này chỉ cho phép tải lên base64 thì tôi sẽ không sử dụng nó ... – Endless

Trả lời

9

Vị trí hiện tại cho file về phía khách hàng sẽ được đại diện bởi dòng này, hay cụ thể hơn đối số thứ hai ở bước trước gia tăng:

var chunk = new Uint8Array(buffer, count++ * chunkSize, segSize); 

tuy nhiên, trong trường hợp này nó tiến (count++) trước khi bạn có thể tái sử dụng nó vì vậy nếu bạn cần các vị trí thực tế (sau đây như pos), bạn có thể giải nén nó bằng cách đơn giản viết lại dòng vào:

var pos = count++ * chunkSize; // here chunkSize = 16kb 
var chunk = new Uint8Array(buffer, pos, segSize); 

Ở đây mỗi cập nhật vị trí sẽ tăng 16kb vì đó là kích thước chunk. Đối với tiến độ sau đó nó được tính toán pos/fileSize * 100. Điều này tất nhiên giả sử sử dụng kích thước bộ đệm không mã hóa.

Trường hợp đặc biệt duy nhất là đoạn cuối cùng, nhưng khi không có nhiều phần còn lại để đọc vị trí phải bằng với chiều dài tệp (fileSize) vì vậy nó nên được khá thẳng về phía trước.

Khi cuộc gọi ajax trở về máy chủ nên có cùng vị trí trừ khi có sự cố (kết nối, ghi thay đổi truy cập, đĩa đầy đủ, v.v.).

2

Bạn có thể sử dụng API người quản lý để đọc các đoạn và gửi nó đến máy chủ từ xa của bạn.

HTML

<input type="file" id="files" name="file" /> Read bytes: 
<span class="readBytesButtons"> 
    <button>Read entire file in chuncks</button> 
</span> 

Javascript

// Post data to your server. 
    function postChunk(obj) { 
    var url = "https://your.remote.server"; 
    return new Promise(function(resolve, reject) { 
     var xhr = new XMLHttpRequest(); 
     xhr.open('post', url, true); 
     xhr.responseType = 'json'; 
     xhr.onload = function() { 
      var status = xhr.status; 
      if (status == 200) { 
       resolve(xhr.response); 
      } else { 
       reject(status); 
      } 
     }; 
     var params = ""; 
     // check that obj has the proper keys and create the url parameters 
      if (obj.hasOwnProperty(action) && obj.hasOwnProperty(server_id) && obj.hasOwnProperty(filepath) && obj.hasOwnProperty(pos) && obj.hasOwnProperty(chunk)) { 
      params += "action="+obj[action]+"&server_id="+obj[server_id]+"&filepath="+obj[filepath]+"&pos="+obj[pos]+"&chunk="+obj[chunk]; 
      } 
     if(params.length>0) { 
     xhr.send(params); 
     } else { 
     alert('Error'); 
     }  
    }); 
    } 
// add chunk to "obj" object and post it to server 
function addChunk(reader,obj,divID) { 
    reader.onloadend = function(evt) { 
     if (evt.target.readyState == FileReader.DONE) { // DONE == 2 
     obj.chunk = evt.target.result; 
     console.log(obj); 
      document.getElementById(divID).textContent += 
      ['Sending bytes: ', obj.pos*16000, ' - ', ((obj.pos*16000)+(obj.pos+1)*obj.chunk.length), 
      '\n'].join(''); 
     // post data to server 
     postChunk(obj).then(function(data) { 
      if(data!=="" && data!==null && typeof data!=="undefined") { 
      // chunk was sent successfully 
      document.getElementById(divID).textContent += 
      ['Sent bytes: ', obj.pos*16000, ' - ', ((obj.pos*16000)+(obj.pos+1)*obj.chunk.length),'\n'].join(''); 
      } else { 
      alert('Error! Empty response'); 
      } 
     }, function(status) { 
      alert('Resolve Error'); 
     }); 
     } 
    }; 
} 
// read and send Chunk 
function readChunk() { 
    var files = document.getElementById('files').files; 
    if (!files.length) { 
     alert('Please select a file!'); 
     return; 
    } 
    var file = files[0]; 
    var size = parseInt(file.size); 
    var chunkSize = 16000; 
    var chunks = Math.ceil(size/chunkSize); 
    var start,stop = 0; 
    var blob = []; 
    for(i=0;i<chunks;i++) { 
    start = i*chunkSize; 
    stop = (i+1)*chunkSize-1; 
    if(i==(chunks-1)) { 
    stop = size; 
    } 
    var reader = new FileReader(); 
    blob = file.slice(start, stop); 
    reader.readAsBinaryString(blob); 
    var obj = {action: 'writeFileChunk', server_id: 'sid', filepath: 'path', pos: i, chunk: ""}; 
    var div = document.createElement('div'); 
    div.id = "bytes"+i; 
    document.body.appendChild(div); 
    addChunk(reader,obj,div.id);  
    } 
} 
// Check for the various File API support. 
if (window.File && window.FileReader && window.FileList && window.Blob) { 
    console.log(' Great success! All the File APIs are supported.'); 
} else { 
    alert('The File APIs are not fully supported in this browser.'); 
} 
    document.querySelector('.readBytesButtons').addEventListener('click', function(evt) { 
    if (evt.target.tagName.toLowerCase() == 'button') { 
     readChunk(); 
    } 
    }, false); 

Bạn có thể kiểm tra ví dụ này trong này Fiddle

Các vấn đề liên quan