Giriş Formundan Base64 kodlu dosya verilerini alın


100

Firebug'da incelediğim bir miktar bilgiyi alabileceğim temel bir HTML formum var.

Tek sorunum , veritabanına kaydedilmesi için bu formda olması gereken sunucuya gönderilmeden önce dosya verilerini base64 kodlamaya çalışıyorum .

<input type="file" id="fileupload" />

Ve Javascript + jQuery'de:

var file = $('#fileupload').attr("files")[0];

Mevcut javascript'e dayalı bazı işlemlerim var: .getAsBinary (), .getAsText (), .getAsTextURL

Ancak bu kullanılabilir metinlerin hiçbiri kullanılamayan 'karakterler' içerdikleri için eklenebilen kullanılabilir metinleri döndürmez - yüklediğim dosyamda bir 'geri gönderme' olmasını istemiyorum ve belirli nesneleri hedefleyen birden fazla forma ihtiyacım olduğu için bu önemli dosyayı alın ve Javascript'i bu şekilde kullanın.

Dosyayı, yaygın olarak bulunan Javascript base64 kodlayıcılarından birini kullanabilecek şekilde nasıl edinmeliyim !?

Teşekkürler

Güncelleme - Ödül burada başlıyor, tarayıcılar arası desteğe ihtiyacınız var !!!

Ben buradayım:

<input type="file" id="fileuploadform" />

<script type="text/javascript">
var uploadformid = 'fileuploadform';
var uploadform = document.getElementById(uploadformid);


/* method to fetch and encode specific file here based on different browsers */

</script>

Çapraz tarayıcı desteğiyle ilgili birkaç sorun:

var file = $j(fileUpload.toString()).attr('files')[0];
fileBody = file.getAsDataURL(); // only would works in Firefox

Ayrıca, IE şunları desteklemez:

var file = $j(fileUpload.toString()).attr('files')[0];

Bu yüzden şununla değiştirmeliyim:

var element = 'id';
var element = document.getElementById(id);

IE Desteği için.

Bu, Firefox, Chrome ve Safari'de çalışır (ancak dosyayı doğru şekilde kodlamaz veya en azından gönderildikten sonra dosya doğru çıkmaz)

var file = $j(fileUpload.toString()).attr('files')[0];
var encoded = Btoa(file);

Ayrıca,

file.readAsArrayBuffer() 

Görünüşe göre sadece HTML5'te mi destekleniyor?

Pek çok kişi önerdi: http://www.webtoolkit.info/javascript-base64.html

Ancak bu, UTF_8 yönteminde base64 kodlamadan önce yalnızca en hatası döndürür? (veya boş bir dize)

var encoded = Base64.encode(file); 

Ne yüklüyorsun Metin verisi mi yoksa ikili mi?
beatgammit

@tjamenson ikili veri - gerçekten 'kelime belgesi' 'pdf' 'görüntü' vb. Dosya adını başka bir değişkene atayacaktım ama neyin mümkün olduğunu anlamamda ölümcül bir kusur olup olmadığını merak etmeye başladım. upload formları ve html - bu yöntem tamamen uygulanamaz mı ve dosya verilerini bir dizge olarak göndererek iletmek mümkün değil mi? Ayrıca okuduğum HTML5 olmadan bazı çözümleri var -
jordan.baucke

İlginç. Neden tarayıcı ve sunucu arasında temel 64 kodlaması yapıyorsunuz ve bunu tarayıcıda gerçekleştirmeye çalışıyorsunuz? Görünüşe göre verileri güvenli hale getirmeye çalışıyorsanız, SSL tüm HTTP verilerini (dosyalar dahil) kablo üzerinden şifrelediği için çok daha kolay olacaktır. Ve veritabanınız için gerekirse 64 sunucu tarafında temel yapabilirsiniz.
William Walseth

@William Verileri güvenli hale getirmeye çalışmıyorum, sadece doğru biçime getirin. Salesforce.com (Apex platformu), kayıt veritabanında oluşturulmadan önce veritabanının base64 olarak kodlanmasını gerektirir, bir form aracılığıyla dosya verilerini base64 kodlama işlevselliği çok zayıf bir şekilde belgelenmiştir (Bu soruyu sorduktan sonra bunu nasıl yapacağımı anladım). Her neyse, base64 kodlamalı ikili dosya verileri yalnızca HTML5 veya Mozilla Dosya API'sinde
jordan.baucke

1
Tamam, şimdi neden buna ihtiyacın olduğunu anladım. Ara sunucu yok + çılgın bulut gereksinimleri + tarayıcılar arası çözüm yok = 1 karışıklık. Afedersiniz.
William Walseth

Yanıtlar:


121

Tarayıcı tarafında javascript'te tamamen mümkündür.

Kolay yol:

ReadAsDataURL () metodu zaten sizin için base64 olarak kodjar. Muhtemelen başlangıçtaki şeyleri çıkarmanız gerekecek (ilkine kadar), ama bu önemli değil. Bu yine de tüm eğlenceyi alacaktır.

Zor yol:

Zor yoldan denemek istiyorsanız (veya işe yaramazsa), bakın readAsArrayBuffer(). Bu size bir Uint8Array verecektir ve belirtilen yöntemi kullanabilirsiniz. Bu, muhtemelen yalnızca, görüntü verilerini değiştirmek veya karşıya yüklemeden önce başka bir büyü yapmak gibi verilerin kendisiyle uğraşmak istiyorsanız yararlıdır.

İki yöntem vardır:

  • Dizeye dönüştürün ve yerleşik btoaveya benzerini kullanın
    • Tüm vakaları test etmedim, ancak benim için çalışıyor - sadece karakter kodlarını al
  • Doğrudan bir Uint8Array'den base64'e dönüştürme

Yakın zamanda tarayıcıya tar uyguladım . Bu sürecin bir parçası olarak, kendi direkt Uint8Array-> base64 uygulamamı yaptım. Buna ihtiyacın olacağını sanmıyorum, ama bir göz atmak istersen burada ; oldukça temiz.

Şimdi ne yapıyorum:

Bir Uint8Array'den dizeye dönüştürme kodu oldukça basittir (burada buf bir Uint8Array'dir):

function uint8ToString(buf) {
    var i, length, out = '';
    for (i = 0, length = buf.length; i < length; i += 1) {
        out += String.fromCharCode(buf[i]);
    }
    return out;
}

Oradan şunu yapın:

var base64 = btoa(uint8ToString(yourUint8Array));

Base64 artık base64 kodlu bir dize olacak ve sadece şeftali gibi yüklemesi gerekiyor. İtmeden önce iki kez kontrol etmek istiyorsanız bunu deneyin:

window.open("data:application/octet-stream;base64," + base64);

Bu, dosyayı bir dosya olarak indirecektir.

Diğer bilgiler:

Verileri bir Uint8Array olarak almak için MDN belgelerine bakın:


harika - readAsArrayBuffer()Doğru base64 verisi gibi görünen çıktıyı düşündüm , ancak dizenin yalvaran kısmı yüzünden işlenmeyecek - şimdi bir şans vereceğim!
jordan.baucke

1
readAsArrayBuffer () Chrome / Safari'de yok gibi görünüyor ve diğer tarayıcılarda sorunlu olacağını varsayıyorum ~ bu diğer tarayıcılarda kullanabileceğim bir eşdeğeri var mı?
jordan.baucke

createObjectURL () <- bu umut verici görünüyor, onu uygulamaya çalışacağım, ancak eminim
IE'nin

İndirme çözümünüzü çalıştırmadan önce bir dosya adı atamak mümkün mü?
Ωmega

@ Ωmega - Hayır. Tüm bunların yaptığı bir ikili akışı indirmek. Bir dosya adı belirlemenin (AFAIK) yolu yoktur. Bazı tarayıcılar bir uzantı tahmin ediyor. Dosya adlarını almak için yüklemeniz ve ardından tekrar indirmeniz gerekir.
beatgammit

38

Benim çözümüm kullanımdı readAsBinaryString()ve btoa()sonucuydu.

uploadFileToServer(event) {
    var file = event.srcElement.files[0];
    console.log(file);
    var reader = new FileReader();
    reader.readAsBinaryString(file);

    reader.onload = function() {
        console.log(btoa(reader.result));
    };
    reader.onerror = function() {
        console.log('there are some problems');
    };
}

3
Açık farkla en kolay yol, neden daha fazla oy almıyor?
sarink

14

Herhangi bir Ajax isteği kullanmadan dosya yükleme düğmesine tıklandığında görüntüyü görüntülemek için FileReader'ı kullandım. Aşağıdaki kod, birisine yardımcı olabileceğini ummaktadır.

$(document).ready(function($) {
    $.extend( true, jQuery.fn, {        
        imagePreview: function( options ){          
            var defaults = {};
            if( options ){
                $.extend( true, defaults, options );
            }
            $.each( this, function(){
                var $this = $( this );              
                $this.bind( 'change', function( evt ){

                    var files = evt.target.files; // FileList object
                    // Loop through the FileList and render image files as thumbnails.
                    for (var i = 0, f; f = files[i]; i++) {
                        // Only process image files.
                        if (!f.type.match('image.*')) {
                        continue;
                        }
                        var reader = new FileReader();
                        // Closure to capture the file information.
                        reader.onload = (function(theFile) {
                            return function(e) {
                                // Render thumbnail.
                                    $('#imageURL').attr('src',e.target.result);                         
                            };
                        })(f);
                        // Read in the image file as a data URL.
                        reader.readAsDataURL(f);
                    }

                });
            });
        }   
    });
    $( '#fileinput' ).imagePreview();
});

1

Bununla kendim mücadele ettikten sonra, onu destekleyen tarayıcılar için FileReader'ı (Chrome, Firefox ve henüz piyasaya sürülmemiş Safari 6) ve POSTed dosya verilerini diğerleri için Base64 kodlu veriler olarak geri yansıtan bir PHP betiğini uygulamaya geldim. tarayıcılar.


0

Ajax stili yükleme için 'iframe'i kullanmanın, HTML5 tam olarak dönene ve uygulamamdaki eski tarayıcıları desteklememe gerek kalmayana kadar durumum için çok daha iyi bir seçim olabileceğini düşünmeye başladım !


Sadece merak, neden sadece yapmayız [ webtoolkit.info/javascript-base64.html#] , ve sonra dışarı-Yorum input = Base64._utf8_encode(input);ve output = Base64._utf8_decode(output);? Utf-8 dönüştürme hatası dışında bir sorun var mı?
shr

@shr Her tarayıcıda bu yöntemlere giriş yapmak için ikili dosya verilerini nasıl yakalayacağımı bilmiyorum? $('#inputid').files[0]( Anladığım kadarıyla IE7'de çalışmıyor ). O kadar kolay olsaydı? var output = Base64.encode($('#inputid').files[0])??
jordan.baucke

0

@ Josef'in cevabından esinlenilmiştir:

const fileToBase64 = async (file) =>
  new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = (e) => reject(e)
  })

const file = event.srcElement.files[0];
const imageStr = await fileToBase64(file)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.