2012-02-25 131 views
8

我想使用javascript将图像文件上传到couchdb中。为此,我使用内联附件概念。上传文件时,我必须使用Base64 encode()。这个方法只有字符串参数。如何将图像文件转换为使用javascript的base64字符串。请任何人都可以与我分享样本片段。将图像文件转换为base64使用javascript的字符串

感谢

+0

不,你已经有图像作为一个字符串,所以你可以上传它? – 2012-02-25 17:12:11

+0

文件如何存储在内存中?包含它的变量的当前类型是什么? – pimvdb 2012-02-25 17:27:33

回答

8

您可以使用canvas支持它的浏览器中,只要图像是从同一个域加载的。

function encodeImage(src, callback) { 
    var canvas = document.createElement('canvas'), 
     ctx = canvas.getContext('2d'), 
     img = new Image(); 

    img.onload = function() { 
     canvas.width = img.width; 
     canvas.height = img.height; 
     ctx.drawImage(img, 0, 0, img.width, img.height); 
     callback(canvas.toDataURL()); 
    } 
    img.src = src; 
} 

查看示例here

+0

作为一个快速提示,这会给你一些形式的“data:image/png; base64,iVBORw0KGgoAAAA ....”。如果你尝试附加这个,Couchdb会给你一个神秘的错误;你需要去除“data:image/png; base64”部分。 – 2013-08-21 10:50:28

1

我用下面的JavaScript的base64编码器/成功解码:http://hellerim.net/base64_src.php

我也做了一些修改这些程序,你可能会发现有用:

/// 
/// 
// This file implements base64 encoding and decoding. 
// Encoding is done by the function base64Encode(), decoding 
// by base64Decode(). The naming mimics closely the corresponding 
// library functions found in PHP. However, this implementation allows 
// for a more flexible use. 
// 
// This implementation follows RFC 3548 (http://www.faqs.org/rfcs/rfc3548.node), 
// so the copyright formulated therein applies. 
// 
// Dr.Heller Information Management, 2005 (http://www.hellerim.de). 
// 
/// 

var base64 = function() { }; 

// provide for class information 
base64.classID = function() { 
    return 'system.utility.base64'; 
}; 

//disallow subclassing 
base64.isFinal = function() { 
    return true; 
}; 

// original base64 encoding 
base64.encString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/'; 
// URL and file name safe encoding 
base64.encStringS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'; 

/// BEGIN_DOC(base64).METHOD(encode) 
/// 
// method String base64.encode(INPUTTYPE inp [, bool uc [, bool safe]]) 
// 
// Encode input data into a base64 character string. 
// 
// Function arguments: 
//  INPUTTYPE inp:  data to be encoded. INPUTTYPE may be String or Array. 
//       Any other INPUTTYPE results in an output value of null. 
//       If INPUTTYPE is String each character is converted into 
//       two bytes each of which is encoded separately. 
//  bool uc    Optional. If this parameter has a value of 'true' which is 
//       the default, code of each character is treated as a 16-bit 
//       entity (UniCode), i.e. as two bytes. Otherwise, the codes 
//       are truncated to one byte (8-bit character set) which 
//       may result in information loss. If INPUTTYPE is Array, 
//       the value of this parameter has no effect. 
//  bool safe:   Optioanal. If this parameter is set to true, the standard base64 
//       character set is replaced with a modified version where 
//       the characters '+' and '/' are replace with '-' and '_', 
//       repectively, in order to avoid problems with file system 
//       namings which otherwise could occur on some systems. 
//       By default, the value of this argument is assumed to be 
//       false. 
// Return value:    The function returns a character string consisting of 
//       the base64 representaion of the input. Its length is a 
//       multiple of 4. If the encoding yields less than this 
//       the string is stuffed with the '=' character. In each case, 
//       the string maybe empty but not null if no error occurred. 
// Errors:     Whenever an error occurs, null is returned. Parameter values 
//       not defined above are considered errors. 
// Remarks:     If the input array contains something different from 
//       a byte at some position the first 8 bits only of this entity are 
//       processed silently without returning an error, which probably 
//       results in garbage converted to base64. 
// 
/// END_DOC 
base64.encode = function (inp, uc, safe) { 
    // do some argument checking 
    if (arguments.length < 1) return null; 
    var readBuf = []; // read buffer 
    if (arguments.length >= 3 && safe != true && safe != false) return null; 
    var enc = (arguments.length >= 3 && safe) ? this.encStringS : this.encString; // character set used 
    var b = (typeof inp == "string"); // how input is to be processed 
    if (!b && (typeof inp != "object") && !(inp instanceof Array)) return null; // bad input 
    if (arguments.length < 2) { 
    uc = true;     // set default 
    } // otherwise its value is passed from the caller 
    if (uc != true && uc != false) return null; 
    var n = (!b || !uc) ? 1 : 2; // length of read buffer 
    // var out = '';     // output string 
    var out = [];     // output string 
    var c = 0;     // holds character code (maybe 16 bit or 8 bit) 
    var j = 1;     // sextett counter 
    var l = 0;     // work buffer 
    var s = 0;     // holds sextett 

    // convert 
    for (var i = 0; i < inp.length; i++) { // read input 
    c = (b) ? inp.charCodeAt(i) : inp[i]; // fill read buffer 
    for (var k = n - 1; k >= 0; k--) { 
     readBuf[k] = c & 0xff; 
     c >>= 8; 
    } 
    for (var m = 0; m < n; m++) {   // run through read buffer 
     // process bytes from read buffer 
     l = ((l << 8) & 0xff00) | readBuf[m]; // shift remaining bits one byte to the left and append next byte 
     s = (0x3f << (2 * j)) & l;    // extract sextett from buffer 
     l -= s;        // remove those bits from buffer; 
     out.push(enc.charAt(s >> (2 * j)));  // convert leftmost sextett and append it to output 
     j++; 
     if (j == 4) {       // another sextett is complete 
     out.push(enc.charAt(l & 0x3f));  // convert and append it 
     j = 1; 
     } 
    } 
    } 
    switch (j) {       // handle left-over sextetts 
    case 2: 
     s = 0x3f & (16 * l);    // extract sextett from buffer 
     out.push(enc.charAt(s));    // convert leftmost sextett and append it to output 
     out.push('==');      // stuff 
     break; 
    case 3: 
     s = 0x3f & (4 * l);     // extract sextett from buffer 
     out.push(enc.charAt(s));    // convert leftmost sextett and append it to output 
     out.push('=');       // stuff 
     break; 
    default: 
     break; 
    } 

    return out.join(''); 

} 

/// BEGIN_DOC(base64).METHOD(decode) 
/// 
// method RETURNTYPE base64.decode(String inp [, enum outType [, bool safe [, bool lax]]]) 
// 
// Encode input data into a base64 character string. 
// 
// Function arguments: 
//  String inp:   base64 encoded data string to be decoded. 
//  enum outType   Optional. This parameter specifies the type of the output and determines 
//       how the input data is to be interpreted.: 
//        0 - binary data; create a byte array (default) 
//        1 - 8-bit character string, assuming 1-byte characters encoded in inp 
//        2 - 16-bit (UniCode) character string, assuming 2-byte 
//         characters encoded in inp 
//       If 2 is passed to the function, but the number of base64 characters 
//       is odd, a value of null is returned. 
//  bool safe    Optional. If this parameter is set to true, the standard base64 
//       character set is replaced with a modified version where 
//       the characters '+' and '/' are replaced with '-' and '_', 
//       repectively, in order to avoid problems with file system 
//       namings which otherwise could occur on some systems. 
//       By default, the value of this argument is assumed to be 
//       false. 
//  bool lax    Optional. If set to true, the function skips all input characters which 
//       cannot be processed. This includes the character '=', too, if 
//       it is followed by at least one different character before the string 
//       ends. However, if skipping infeasible characters amounts to a number 
//       of allowed base64 characters which is not amultiple of 4, 
//       this is considered an error and null is returned. 
//       If lax is set to false (the default), null is returned 
//       whenever an infeasible character is found. 
//       The purpose of this parameter is to give support in cases 
//       where data has been base64 encoded and later on was folded by 
//       some other software, e.g. '\r\n\'s have been inserted in email. 
//       exchange. 
// Return value:    The function's processing result value is stored in a string or in 
//       a byte array before it is returned, depending on the value 
//       assigned to the type parameter. In each case, the value 
//       maybe empty but not null if no error occurred. 
// Errors:     Whenever an error occurs, null is returned. Parameter values 
//       not defined above are considered errors. 
// 
/// END_DOC 

base64.decode = function (inp, outType, safe, lax) { 

    // do some argument checking 
    if (arguments.length < 1) return null; 
    if (arguments.length < 2) outType = 0; // produce character array by default 
    if (outType != 0 && outType != 1 && outType != 2) return null; 
    if (arguments.length >= 3 && safe != true && safe != false) return null; 
    var sEnc = (arguments.length >= 3 && safe) ? this.encStringS : this.encString; // select encoding character set 
    if (arguments.length >= 4 && lax != true && lax != false) return null; 
    var aDec = {};    // create an associative array for decoding 
    for (var p = 0; p < sEnc.length; p++) { // populate array 
    aDec[sEnc.charAt(p)] = p; 
    } 
    var out = (outType == 0) ? [] : ''; 
    lax = (arguments.length == 4 && lax); // ignore non-base64 characters 
    var l = 0;    // work area 
    var i = 0;    // index into input 
    var j = 0;    // sextett counter 
    var c = 0;    // input buffer 
    var k = 0;    // index into work area 
    var end = inp.length; // one position past the last character to be processed 
    var C = ''; 
    // check input 
    if (lax) { 
    var inpS = '';   // shadow input 
    var ignore = false; // determines wether '=' must be counted 
    var cnt = 0; 
    for (var p = 1; p <= inp.length; p++) { // check and cleanup string before trying to decode 
     c = inp.charAt(end - p); 
     if (c == '=') { 
     if (!ignore) { 
      if (++cnt > 1) ignore = true; 
     } else { 
      continue; 
     } 
     } else if (undefined != aDec[c]) { // the character is base64, hence feasible 
     if (!ignore) ignore = true;  // no more '=' allowed 
     inpS = c + inpS;     // prepend c to shadow input 
     } 
    } 
    for (var p = 0; p <= cnt; p++) {  // at most cnt '=''s were garbage, a number in 
     if (p == 2) return null;   // [inpS.length, inpS.length + cnt] must be a 
     if ((inpS.length + cnt) % 4 == 0) break; // multiple of 4 
    } 
    if (inpS.length % 4 == 1) return null; // must be 0, 2, or 3 for inpS to contain correctly base64 encoded data 
    inp = inpS;       // inp now contains feasible characters only 
    end = inp.length; 
    } else { 
    if (inp.length % 4 > 0) return null; // invalid length 
    for (var p = 0; p < 2; p++) {  // search for trailing '=''s 
     if (inp.charAt(end - 1) == '=') { 
     end--; 
     } else { 
     break; 
     } 
    } 
    } 
    // convert 
    for (i = 0; i < end; i++) { 
    l <<= 6;        // clear space for next sextett 
    if (undefined == (c = aDec[inp.charAt(i)])) return null; // lax must be false at this place! 
    l |= (c & 0x3f); // append it 
    if (j == 0) { 
     j++; 
     continue;       // work area contains incomplete byte only 
    } 
    if (outType == 2) { 
     if (k == 1) {      // work area contains complete double byte 
     out += String.fromCharCode(l >> (2 * (3 - j))); // convert leftmost 16 bits and append them to string 
     l &= ~(0xffff << (2 * (3 - j)));  // clear the 16 processed bits 
     } 
     k = ++k % 2; 
    } else {        // work area contains complete byte 
     if (outType == 0) { 
     out.push(l >> (2 * (3 - j)));   // append byte to array 
     } else { 
     out += String.fromCharCode(l >> (2 * (3 - j))); // convert leftmost 8 bits and append them to String 
     } 
     l &= ~(0xff << (2 * (3 - j)));   // clear the 8 processed bits 
    } 
    j = ++j % 4;       // increment sextett counter cyclically 
    } 
    if (outType == 2 && k == 1) return null; // incomplete double byte in work area 

    return out; 
} 
0

couchDB中包含base64函数。 请参阅this最近的问题&答案。

1

这里是我做了什么:

function addAttachment(inputId, inputDb) { 
    var db = $.couch.db(inputDb); 
    var file = document.getElementById("attachment").files[0]; 
    var reader = new FileReader(); 

    reader.onloadend = function() { 
     //That's CouchDB's internal Base64. 
     var base64 = Base64.encode(reader.result); 
      db.openDoc(inputId, { 
      success:function (result) { 
       db.saveDoc({ 
        "_id": inputId, 
        "_rev":result._rev, 
        "_attachments": { 
         "yourImageHere.jpg": 
         { 
          "content_type":"image\/jpeg", 
          "data": base64 
         } 
        } 
       }, { 
        success : function() { 
         location.reload(); 
        }, 
        error : function (a, b, c) { 
         alert('Cannot save'); 
        } 
       }); 
      }, 
      error:function (a, b, c) { 
       alert('Error: ' + c); 
      } 
     }); 
    } 

    if (file) { 
     reader.readAsBinaryString(file); 
    } 
} 

而我的HTML:

<form id="upload" method="post" enctype="multipart/form-data" > 
    <input type="file" id="attachment" name="_attachments"/> 
    <br/> 
    <input type="button" value="Submit"/> 
</form> 

是很重要的,你读成二进制(readAsBinaryString)和Base64编码使用CouchDB的内部库转换:

<script src="/_utils/script/base64.js"></script> 
相关问题