我们通过拖放变量来接收本地文件(通常是PDF,PNG或JPG)(使用dropzone.js - 在此阶段它是base64加上指定文件类型的字符)。我们将它(现在是二进制)加密为javascript变量。然后,我们使用该变量创建一个Blob,并将其上传到运行PHP的服务器。 (见our finding out how to send a js variable to PHP $_FILE。)
我们发现blob的.size比我们上传的文件的.length大约50%。 (我们通过转换为base64上传然后使用JSON上传,但我们希望改变的一个原因是希望避免使用base64大小增加33%。)
从中等大小到大尺寸,斑点总是大约50%。作为一个小测试,我们使用120个字符作为输入创建了一个Blob,发现Blob.size为210.(我们通常使用正确的file.type; image / png只是将它解释为二进制数据而不是'需要编码。)从我们代码中的实际使用情况来看:我们上传了一个900K的PDF文件。类型类似于'application / pdf'。得到的斑点就像1,400K。也试过PNG。
我认为Blob应该与输入大小相同,不是吗?我们可能做错了什么?
new Blob(["123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"], {type:"image/png"});
答案 0 :(得分:2)
有三个因素导致了规模的增加。
我们的第一个问题是我们使用FileReader的readAsDataURL读取文件。这会读取一个文件并在base64中对其进行编码,这会导致大小增加大约33%。我们更改为readAsArrayBuffer并读入Uint8Array(8位字节的数组)。
我们将文件传递给加密系统forge.js并且只将数据作为字符串传递,因此我们必须将二进制ArrayBuffer转换为字符串。我们使用more performant solution here。 This reference更全面,指的是相对较新的TextEncoder / Decoder API。我们还没有使用它们。我猜他们表现得更好,因为他们纯粹是原生的。
一旦伪造进行加密,我们必须转换为Blob,所以请参阅this了解如何将ArrayBuffer转换为Blob和从Blob转换。
其次,正如@TechnicalChaos指出的那样,我们在javascript中使用二进制字符串。这种编码使它的大小更大,因为javascript中的字符串以2字节字符编码。
然后可以将blob附加到要上传到我们的PHP服务器的表单中的$ _FILE。
现在我们的上传大小与我们加密的文件大小相同。
答案 1 :(得分:1)
在将二进制数据放入Javascript blob中时,我遇到了类似的问题-事实证明,Blob假定采用UTF-8编码,因此某些原始数据字节最终以多字节字符结尾。
解决方案是将二进制数据的每个字节放入Uint8Array中,然后将其传递给Blob。