2013-03-26 14 views
15

Fotoğrafları yeniden boyutlandıran ve yükleyen cep telefonları için bir web sitesi oluşturuyorum.Android'e yüklenen boş dosyalar Yerel tarayıcı

$('#ImgPreview canvas').each(function(pIndex) { 
    vFormData.append(pIndex, canvasToJpegBlob($(this)[0]), vIssueId +'-attachment0'+ pIndex +'.jpg'); 
}); 

$.ajax({ 
    url: '/api/ob/issuefileupload', 
    data: vFormData, 
    processData: false, 
    contentType: false, 
    type: 'POST' 
}).done(function(pData) { 
    window.location = '/issue?id='+ vIssueId; 
}).fail(function(pJqXHR) { 
    alert(My.Strings.UploadFailed); 
}); 

Bu Android ve iOS Safari'de Chrome'da çalışır, ancak yerel Android tarayıcıda, dosyaları 0 içerik uzunluğu ve adı Blob'u + bir UID var. Dosya formdata eklendiğinde boyut da oldukça büyük (Chrome'da 50k'ya karşı 900k) görünüyor.

canvasToJpegBlob fonksiyonu:

function canvasToJpegBlob(pCanvas) { 
    var vMimeType = "image/jpeg", 
     vDataURI, 
     vByteString, 
     vBlob, 
     vArrayBuffer, 
     vUint8Array, i, 
     vBlobBuilder; 

    vDataURI = pCanvas.toDataURL(vMimeType, 0.8); 
    vByteString = atob(vDataURI.split(',')[1]); 

    vArrayBuffer = new ArrayBuffer(vByteString.length); 
    vUint8Array = new Uint8Array(vArrayBuffer); 
    for (i = 0; i < vByteString.length; i++) { 
     vUint8Array[i] = vByteString.charCodeAt(i); 
    } 

    try { 
     vBlob = new Blob([vUint8Array.buffer], {type : vMimeType}); 
    } catch(e) { 
     window.BlobBuilder = window.BlobBuilder || 
          window.WebKitBlobBuilder || 
          window.MozBlobBuilder || 
          window.MSBlobBuilder; 

     if (e.name === 'TypeError' && window.BlobBuilder) { 
      vBlobBuilder = new BlobBuilder(); 
      vBlobBuilder.append(vUint8Array.buffer); 
      vBlob = vBlobBuilder.getBlob(vMimeType); 
     } else if (e.name === 'InvalidStateError') { 
      vBlob = new Blob([vUint8Array.buffer], {type : vMimeType}); 
     } else { 
      alert(My.Strings.UnsupportedFile); 
     } 
    } 

    return vBlob; 
} 

yerel Android tarayıcıda bu çalışma almak için herhangi bir yolu var mı?

+3

:

var fd = needsFormDataShim ? new FormDataShim() : new FormData(); 

+0

Hayır, henüz bir çözüm bulamadınız. – bjornarvh

+0

Burada aynı sorun var - Bir ödül ekledim. –

cevap

6

Ayrıca bu soruna rastladım ve bazı durumlarda sunucu tarafı kodu üzerinde kontrol sahibi olmayacağından daha genel bir çözüm bulmam gerekiyordu.

Neredeyse tamamen şeffaf olan bir çözüme ulaştım. Yaklaşım, için gerekli formatta veri ekleyen bir blob ile kırılmış FormData'u çok doldurmaktı. XHR'nin send()'u, blob'u istekte gönderilen bir arabelleğe okuyan bir sürümle geçersiz kılar. sonradan normal fd.append(name, value) arayarak,

var 
    // Android native browser uploads blobs as 0 bytes, so we need a test for that 
    needsFormDataShim = (function() { 
     var bCheck = ~navigator.userAgent.indexOf('Android') 
         && ~navigator.vendor.indexOf('Google') 
         && !~navigator.userAgent.indexOf('Chrome'); 

     return bCheck && navigator.userAgent.match(/AppleWebKit\/(\d+)/).pop() <= 534; 
    })(), 

    // Test for constructing of blobs using new Blob() 
    blobConstruct = !!(function() { 
     try { return new Blob(); } catch (e) {} 
    })(), 

    // Fallback to BlobBuilder (deprecated) 
    XBlob = blobConstruct ? window.Blob : function (parts, opts) { 
     var bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder); 
     parts.forEach(function (p) { 
      bb.append(p); 
     }); 

     return bb.getBlob(opts ? opts.type : undefined); 
    }; 

function FormDataShim() { 
    var 
     // Store a reference to this 
     o = this, 

     // Data to be sent 
     parts = [], 

     // Boundary parameter for separating the multipart values 
     boundary = Array(21).join('-') + (+new Date() * (1e16*Math.random())).toString(36), 

     // Store the current XHR send method so we can safely override it 
     oldSend = XMLHttpRequest.prototype.send; 

    this.append = function (name, value, filename) { 
     parts.push('--' + boundary + '\nContent-Disposition: form-data; name="' + name + '"'); 

     if (value instanceof Blob) { 
      parts.push('; filename="'+ (filename || 'blob') +'"\nContent-Type: ' + value.type + '\n\n'); 
      parts.push(value); 
     } 
     else { 
      parts.push('\n\n' + value); 
     } 
     parts.push('\n'); 
    }; 

    // Override XHR send() 
    XMLHttpRequest.prototype.send = function (val) { 
     var fr, 
      data, 
      oXHR = this; 

     if (val === o) { 
      // Append the final boundary string 
      parts.push('--' + boundary + '--'); 

      // Create the blob 
      data = new XBlob(parts); 

      // Set up and read the blob into an array to be sent 
      fr = new FileReader(); 
      fr.onload = function() { oldSend.call(oXHR, fr.result); }; 
      fr.onerror = function (err) { throw err; }; 
      fr.readAsArrayBuffer(data); 

      // Set the multipart content type and boudary 
      this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); 
      XMLHttpRequest.prototype.send = oldSend; 
     } 
     else { 
      oldSend.call(this, val); 
     } 
    }; 
} 

Ve sadece bu yüzden gibi kullanın:

// not use blob, simply use key value 
var form = new FormData(); 
// get you content type and raw data from data url 
form.append('content_type', type); 
form.append('content', raw); 
+0

sonunu kesmek gibi görünüyor Bu çözüm gönderme için teşekkürler. Benim için çalışmıyor. Sunucum istek verilerini ayrıştıramadı. '' ' ---------------------- 1e3xa79f9edc04cok0c İçerik-: Ve Krom İnceleyicisi'nde, istek yükü bu (o yapıştırılan başlangıcı) benziyor Yerleştirme: form-veri; = "Fotoğraf" adını; dosya = "leke" içerik türü: görüntü/JPEG ÿØÿàJFIFÿÛC (1 # (%: Mqypdx \ egcÿÛC // cB8Bcccccccccccc ' 3 = normal olarak ise FormData, dosya verileri gizli.FYI, Chrome'u test amaçlı shim kullanmaya zorluyorum.Ancak sonuç Android 4.1'de aynı. – jacob

+0

Tamam \ n yerine \ r \ n kullanarak çalıştım. Taşıyıcı dönüşünü kullanmak için HTTP özelinde (http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4) ve sunucum (Django) bunu ayrıştırmayı gerektiriyor. Chrome ile ilgili son notum görüntüleniyor ikili dosya verileri hala oluşur, ancak muhtemelen FormData için özel bir durumdur ve etkilemez. – jacob

+0

@jacob, işe yaradığına sevindim. Bu yüzden, cevabı güncelleyemiyorum ama düzenleme düğmesine basmaktan çekinmeyin. Geri döndüğümde tavsiyenizi alıp kendi kodumda taşıma dönüşünü kullanacağım. Şerefe ;-) –

1

Tuval üzerine çizmeye çalışarak, matris kullanarak boyutunu istediğiniz boyuta ölçeklendirin ve ardından canvas.toDataURL kullanarak sunucuya gönderin. Bu question göz atın.

+2

Sorunun yanlış anlaşıldığını görüyorum. Bunun bir mobil web sitesi değil, bir uygulama için olduğunu belirtmek üzere şimdi düzenledik. – bjornarvh

+0

@bjornarvh benim yeni çözümümü dene –

+0

Görüntüyü, bunun yerine base64 kodlu bir dize olarak göndererek işe koydu. Normal dosya yükleme ile ilgili bir çözüm olmadığı için bunu cevap olarak işaretledi. – bjornarvh

1

i sorunu çözmek için kullanabilir

İşte ana kod Hey, bu işe yaradığın bir ihtimal var, ben de aynı sorunla uğraştım!

İlgili konular