2011-10-13 2 views
2

아시다시피 HTML 5는 멋진 FileAPI를 제공합니다. 나는 사용자가 Base64로 인코딩 된 문자열을받는 시스템을 만들었으며 디스크에 기록해야합니다 (Google 크롬 앱이기 때문에 적절한 권한이 있습니다). 내 코드는 다음과 같습니다HTML5 이진 파일 쓰기 Base35

function onInitFs(fs){  
    fs.root.getFile(fileName, {create: true}, function(fileEntry) { 
    fileEntry.createWriter(function(fileWriter) { 
     var bb = new window.WebKitBlobBuilder(); 
     bb.append(atob(dataInBase64Format)); 
     fileWriter.write(bb.getBlob());   
    }, errorHandler); 
    console.log(fileEntry.toURL()); 
    }, errorHandler); 
} 

그러나, 내 원래 파일 크기가 (조금 불필요한 것들을 삭제) : 6,302,446 바이트, 서버는 8,403,264 바이트를 Base64로 보내 그러나 저장된 파일이 9,242,715 바이트입니다. 물론 나는 무언가가 잘못되었다는 것을 알고 파일을 보았고 그것은 좋은 문자열 일뿐입니다. 멋진 문자가 표시되지 않습니다. 나는 텍스트 모드로 작성하고 atob은 다른 문자열로 변환한다고 가정합니다. 나는 이진 형식 (아마 배열에서?)으로 변환해야하고 내 fileWriter가 텍스트 모드가 아닌 이진 모드로 쓰도록 강요해야합니다. 웹을 검색했지만 해결책을 찾지 못했습니다. StackOverflow Are Google Chrome Base64 methods capable of handling binary data from the File API?에 대한이 질문을 발견했지만 도움이되지 않았다.

어떻게 Base64 문자열을 적절한 데이터 구조로 변환하고 fileWriter에 기록 할 수 있습니까?

+0

. Blob 사양 (https://w3c.github.io/FileAPI/#blob)에서 원인을 발견했습니다. 그것은 DOMString을 UTF-8로 바꾸는 것을 시도합니다. 이렇게하면 문자열의 유효하지 않은 유니 코드 문자가 U + FFFD 대체 문자로 바뀝니다. 분명히 이것은 여러분이 추가하려고하는 바이너리 데이터에 매우 나쁜 영향을 미친다. – thenickdude

답변

8

크롬을 사용하여 스크린 샷을 캡처하고 캔버스에 넣은 다음 크기를 조정 한 다음 파일 시스템 API를 사용하여 캔버스 데이터를 저장하는 확장 프로그램을 작성했습니다. 이 코드가 직접 코드와 비슷한 코드인지는 모르겠지만 대부분의 코드로 충분할 것입니다.

이 경우, 내 dataURI (예 : myCanvas.toDataURL("image/png"))은 dataInBase64Format과 동일한 Base64 형식으로 가정합니다.

기능 :

// canvas.toBlob is not implemented in Chrome yet! So we have to build the blob ourselves. 
// Derived from http://mustachified.com/master.js 
// via http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-April/031243.html 
// via https://bugs.webkit.org/show_bug.cgi?id=51652 
// via http://code.google.com/p/chromium/issues/detail?id=67587 

function dataURItoBlob(dataURI, callback) { 
    // 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); 
    } 

    // write the ArrayBuffer to a blob, and you're done 
    var bb = new window.WebKitBlobBuilder(); 
    bb.append(ab); 
    return bb.getBlob(mimeString); 
} 

사용법 : 나도이 문제가되었다

// Save image data 
function onInitFs(fs){ 
    fs.root.getFile(fileName, {create:true}, function(fileEntry) { 
     fileEntry.createWriter(function(fileWriter) { 
      fileWriter.write(dataURItoBlob(myCanvas.toDataURL("image/png"))); 
     }, fileErrorHandler); 
    }, fileErrorHandler); 
}, fileErrorHandler); 
+2

당신이 옳다는 것은, int8 배열로 base64 데이터를 변환하는 것입니다. 시도하지는 않았지만 바이트 배열로 변환해야한다고 생각했습니다. 그래서 당신의 대답이 내가 찾고있는 것입니다. – Mustafa

+1

크리스, 고마워요! 귀하의 의견은 정말 많은 도움이되었습니다! – Mourner

+4

WebKitBlobBuilder (또는 BlobBuilder)가 이제 더 이상 사용되지 않고 사용할 수 없으므로 다음을 사용해야합니다. var dataView = new DataView (ab); 새로운 Blob ([dataView], {type : mimeString})을 반환합니다. ArrayBuffer에서 blob을 가져 오려면 – Asaf