2013年6月27日 星期四

利用formData來達成ajax上傳檔案

最近手邊有個案子用到canvas來做圖片的合成,並且要將輸出圖片存到facebook相簿中,一般來說這種要將圖片合成的功能都在server-side完成,這次用canvas除了為了省時以外,也想盡量減輕server-side的負擔。就這個專案的需求來說,操作canvas不是難事,但是以canvas.toDataURL輸出的dataURL要怎麼以file的形式post到fb呢?


首先,要把 dataURL轉成blob

下面這四點是我在stackoverflow上查到的四個步驟:
  1. Take a bytearray or any other data
  2. Convert it to base64
  3. Convert it to blob
  4. Send it as a normal file with Ajax/xhr/FormData using your favorite method
下面這段程式碼就是上述的1~3個步驟

function (dataURI) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs
    var byteString = atob(dataURI.split(',')[1]);

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

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

    var blob = new Blob([ab]);
    return blob;
}

不要問我上面的code怎麼來的,我抄來的!(挺)
接下來我曾經好傻好天真的認為可以把blob塞進form的欄位中,然後把它submit出去,但最後發現是不可以的...


用Ajax將檔案post出去吧


查了一下發現最方便的方式是使用formData物件,只要只用他的append方法就能把blob或string append上去:
var fd = new FormData();
fd.append("source", blob);
接下來只要將他post出去就好囉:
var xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(fd);