在 Javascript 中将 base64 转换为文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22589680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert a base64 to a file in Javascript
提问by Imnl
The goal is to transform a base64 string into a sendable jpg file, I cant use the html input type file but i have to serve in the same format. I am bit lost with file generation. (I am on a client side mobile app).
目标是将 base64 字符串转换为可发送的 jpg 文件,我不能使用 html 输入类型文件,但我必须以相同的格式提供服务。我对文件生成有点迷茫。(我在客户端移动应用程序上)。
This is what i have:
这就是我所拥有的:
file = "data:image/jpg;base64,#{imageData}"
imageData is the base64 string
imageData 是 base64 字符串
There is a way to transform this into a valid file?
有没有办法将其转换为有效文件?
回答by enhzflep
Disclaimer: Produces an invalid result (close, but invalid)
免责声明:产生无效结果(关闭,但无效)
I've done the reverse earlier last week - that is, load an image as binary data (to get around the requirement to run file from localhost).
上周早些时候我做了相反的事情 - 即,将图像作为二进制数据加载(以解决从本地主机运行文件的要求)。
In it, I:
其中,我:
- loaded the file
- base64 converted it
- added a pre-amble to the base64 string
- set the constructed string to be the src of an img element
- 加载文件
- base64 转换了它
- 向 base64 字符串添加了前导码
- 将构造的字符串设置为 img 元素的 src
This worked just fine. Upon reading your question, I tried to simply reverse the process. I was however, unsuccessfull somewhere. The data is extracted from the image correctly, then somewhere afterwards (I think in the call to atob that un-encodes it) the data is messed-up.
这工作得很好。阅读您的问题后,我试图简单地颠倒这个过程。然而,我在某处不成功。数据是从图像中正确提取的,然后在之后的某个地方(我认为在调用 atob 时对其进行了取消编码)数据被弄乱了。
The saved files are an unexpected size, have an added char before "%PNG" and have some missing data in the middle of the file. I'm rather perplexed at this point, to be honest.
保存的文件大小意外,在“%PNG”之前添加了一个字符,并且文件中间有一些丢失的数据。老实说,我在这一点上很困惑。
Anyhow, here's the code I've tried:
无论如何,这是我尝试过的代码:
1. Code to read a file and stuff the data into an element
1. 读取文件并将数据填充到元素中的代码
// fileVar is an object as returned by <input type='file'>
// imgElem is an <img> element - (doesn't need to be added to the DOM)
function loadImgFromFile(fileVar, imgElem)
{
var fileReader = new FileReader();
fileReader.onload = onFileLoaded;
fileReader.readAsBinaryString(fileVar);
function onFileLoaded(fileLoadedEvent)
{
var result,data;
data = fileLoadedEvent.target.result;
result = "data:";
result += fileVar.type;
result += ";base64,";
result += btoa(data);
imgElem.src = result;
}
}
2. Attempt to grab data from an image/canvas and force the download of it using a programmer-supplied filename.
2. 尝试从图像/画布中获取数据并使用程序员提供的文件名强制下载它。
<!doctype html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e)}
function newEl(tag){return document.createElement(tag)}
window.addEventListener('load', onPageLoaded, false);
function onPageLoaded(evt)
{
var imgElem = byId('srcImg');
imgElem.onload = function(){saveImgAsFile( byId('srcImg'), "myImage.png" );};
// simple result of canvas.toDataURL() called on a 5x5 pixel image of a '+'
imgElem.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2NkQID/QCYjiAsmoABFEMRBAThVYmgHAAhoBQWHhfyYAAAAAElFTkSuQmCC";
// use the below line instead of the one above, if you wish to assign an actual image file, rather than the result of call to canvas.toDataURL()
// the base64 string allows me to keep it all in the one file, also, to run if opened via a double-click, rather than having to run from localhost
// imgElem.src = "img/1x1.png";
}
function saveImgAsFile(imgElem, fileName)
{
// get a base64 encoded string from an image element
var srcElem = imgElem;
var dstCanvas = newEl('canvas');
dstCanvas.width = srcElem.naturalWidth;
dstCanvas.height = srcElem.naturalHeight;
var ctx = dstCanvas.getContext('2d');
ctx.drawImage(srcElem,0,0);
var imgSrcStr = dstCanvas.toDataURL();
// extract the image type
var colonPos = imgSrcStr.indexOf(":");
var semiColonPos = imgSrcStr.indexOf(";");
var imgType = imgSrcStr.slice(colonPos+1, semiColonPos);
console.log("image type: " + imgType);
// extract the image data
var commaPos = imgSrcStr.indexOf(',');
var base64ImgString = imgSrcStr.slice(commaPos + 1);
console.log("Data: " + base64ImgString);
// holds the data that is actually written to disk for this image
//** I think the error occurs during this step **//
var unencodedImage = atob(base64ImgString);
var imgFileAsBlob = new Blob( [unencodedImage], {type: imgType} );
var fileNameToUse = fileName;
var downloadLink = newEl('a');
downloadLink.download = fileNameToUse;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null)
{
// Chrome allows the link to be clicked
// without actually adding it to the DOM.
downloadLink.href = window.webkitURL.createObjectURL(imgFileAsBlob);
}
else
{
// Firefox requires the link to be added to the DOM
// before it can be clicked.
downloadLink.href = window.URL.createObjectURL(imgFileAsBlob);
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
}
/*
function saveTextAsFile()
{
var textToWrite = "This is just some random content";
var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'})
var fileNameToSaveAs = "myFile.txt";
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null)
{
// Chrome allows the link to be clicked
// without actually adding it to the DOM.
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
}
else
{
// Firefox requires the link to be added to the DOM
// before it can be clicked.
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
}
*/
function destroyClickedElement(event)
{
document.body.removeChild(event.target);
}
</script>
</head>
<body>
<img id='srcImg'/>
</body>
</html>