2011-10-10 37 views
7

Tôi phải tạo trình tải lên hình ảnh cho một dự án trong tương lai (Không có flash, IE10 +, FF7 + v.v.) để thay đổi kích thước/chuyển đổi hình ảnh trên máy khách và không phải trên máy chủ.Cách tải lên/POST nhiều phần tử canvas

Vì vậy, tôi đã tạo giao diện javascript nơi người dùng có thể 'tải lên' tệp của họ và trực tiếp nhận được/cắt trực tiếp trong trình duyệt mà không cần liên hệ với máy chủ. Hiệu suất là OK, không phải là tốt, nhưng nó hoạt động.

Endresult là một mảng các phần tử canvas. Người dùng có thể chỉnh sửa/cắt các hình ảnh sau khi chúng được thay đổi kích cỡ, vì vậy tôi giữ chúng dưới dạng canvas thay vì chuyển đổi chúng thành jpeg. (Điều này sẽ làm xấu đi hiệu suất ban đầu)

Bây giờ công việc này tốt, nhưng tôi không biết cách tốt nhất để tải các thành phần canvas đã hoàn thành lên máy chủ ngay bây giờ là gì. (Sử dụng trình xử lý chung asp.net 4 trên máy chủ)

Tôi đã thử tạo đối tượng json từ tất cả các phần tử chứa dataurl của mỗi canvas.

Vấn đề là, khi tôi có 10-40 hình ảnh, trình duyệt bắt đầu đóng băng khi tạo dataurls, đặc biệt là đối với hình ảnh lớn hơn 2 megabyte.

  //images = array of UploadImage 
      for (var i = 0; i < images.length; i++) { 
       var data = document.getElementById('cv_' + i).toDataURL('image/jpg'); 
       images[i].data = data.substr(data.indexOf('base64') + 7); 
      } 

Cũng chuyển đổi chúng thành đối tượng json (Tôi đang sử dụng json2.js) thường xuyên làm hỏng trình duyệt của mình. (FF7)

đối tượng My

var UploadImage = function (pFileName, pName, pDescription) { 
     this.FileName = pFileName; 
     this.Name = pName; 
     this.Description = pDescription; 
     this.data = null; 
    } 

Việc tải thói quen

  //images = array of UploadImage 
      for (var i = 0; i < images.length; i++) { 
       var data = document.getElementById('cv_' + i).toDataURL('image/jpg'); 
       images[i].data = data.substr(data.indexOf('base64') + 7); 
      } 

      var xhr, provider; 
      xhr = jQuery.ajaxSettings.xhr(); 
      if (xhr.upload) { 
       xhr.upload.addEventListener('progress', function (e) { 
        console.log(Math.round((e.loaded * 100)/e.total) + '% done'); 
       }, false); 
      } 
      provider = function() { 
       return xhr; 
      }; 
      var ddd = JSON.stringify(images); //usually crash here 
      $.ajax({ 
       type: 'POST', 
       url: 'upload.ashx', 
       xhr: provider, 
       dataType: 'json', 
       success: function (data) { 
        alert('ajax success: data = ' + data); 
       }, 
       error: function() { 
        alert('ajax error'); 
       }, 
       data: ddd 
      }); 

Điều gì sẽ là cách tốt nhất để gửi các phần tử canvas đến máy chủ?

Tôi có nên gửi tất cả cùng một lúc hoặc từng cái một không?

+2

Đây là một câu hỏi khá thú vị . Bạn không chắc chắn tại sao 2 phiếu giảm giá không có bất kỳ nhận xét nào, +1 –

+1

Tại sao câu hỏi này lại bị bỏ qua? – Pointy

+0

Tạo url dữ liệu và gửi nó cùng một lúc. Điều này sẽ làm giảm việc sử dụng bộ nhớ. Nó cũng cho phép bạn hiển thị tiến trình (là xhr2 không được hỗ trợ). Mặt khác là logic máy chủ sẽ dễ dàng hơn và sử dụng bộ nhớ trên máy chủ sẽ ít hơn. – Gerben

Trả lời

5

Tải lên từng tệp một tốt hơn. Yêu cầu ít bộ nhớ hơn và ngay sau khi một tệp sẵn sàng tải lên, quá trình tải lên có thể được bắt đầu thay vì chờ trong khi tất cả các tệp sẽ được chuẩn bị.

Sử dụng FormData để gửi tệp. Cho phép tải lên các tệp ở định dạng nhị phân thay vì mã hóa base64.

var formData = new FormData; 

Nếu Firefox sử dụng canvas.mozGetAsFile ('image.jpg') thay vì canvas.toDataUrl(). Cho phép tránh chuyển đổi không cần thiết từ base64 sang nhị phân.

var file = canvas.mozGetAsFile('image.jpg'); 
formData.append(file); 

Trong Chrome sử dụng để chuyển đổi BlobBuilder base64 vào blob (xem dataURItoBlob chức năng

chấp nhận Sau khi chơi xung quanh với một vài điều, tôi quản lý để con số này ra bản thân mình.

Trước hết, điều này sẽ chuyển đổi một dataURI đến một Blob:

//added for quick reference 
function dataURItoBlob(dataURI) { 
    // convert base64/URLEncoded data component to raw binary data held in a string 
    var byteString; 
    if (dataURI.split(',')[0].indexOf('base64') >= 0) 
     byteString = atob(dataURI.split(',')[1]); 
    else 
     byteString = unescape(dataURI.split(',')[1]); 

    // separate out the mime component 
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; 

    // write the bytes of the string to a typed array 
    var ia = new Uint8Array(byteString.length); 
    for (var i = 0; i < byteString.length; i++) { 
     ia[i] = byteString.charCodeAt(i); 
    } 

    return new Blob([ia], {type:mimeString}); 
} 

Từ this question):

var blob = dataURItoBlob(canvas.toDataURL('image/jpg')); 
formData.append(blob); 

Và sau đó gửi các đối tượng formData. Tôi không chắc chắn làm thế nào để làm điều đó trong jQuery, nhưng với XHR đồng bằng đối tượng nó như vậy:

var xhr = new XMLHttpRequest; 
xhr.open('POST', 'upload.ashx', false); 
xhr.send(formData); 

Trên máy chủ bạn có thể nhận được tập tin từ tập tin bộ sưu tập:

context.Request.Files[0].SaveAs(...); 
+0

Điều này hoạt động tốt, cảm ơn bạn. – elch

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