有什么方法可以在客户端创建一个文本文件并提示用户下载它,而无需与服务器进行任何交互?我知道我不能直接写入他们的机器(安全和所有),但我可以创建并提示他们保存它吗?
适用于 HTML5 浏览器的简单解决方案...
函数下载(文件名,文本){ var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('下载', 文件名); element.style.display = '无'; document.body.appendChild(元素);元素.click(); document.body.removeChild(元素); } 形式 * { 显示:块;边距:10px; }
用法
download('test.txt', 'Hello world!');
您可以使用数据 URI。浏览器支持各不相同;见Wikipedia。例子:
<a href="data:application/octet-stream;charset=utf-16le;base64,//5mAG8AbwAgAGIAYQByAAoA">text file</a>
八位字节流是强制下载提示。否则,它可能会在浏览器中打开。
对于 CSV,您可以使用:
<a href="data:application/octet-stream,field1%2Cfield2%0Afoo%2Cbar%0Agoo%2Cgai%0A">CSV Octet</a>
试试 jsFiddle demo。
IE 10+、Firefox 和 Chrome 的示例(并且没有 jQuery 或任何其他库):
function save(filename, data) {
const blob = new Blob([data], {type: 'text/csv'});
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
}
else{
const elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = filename;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
}
请注意,根据您的情况,您可能还想在删除 elem
后调用 URL.revokeObjectURL。根据 URL.createObjectURL 的文档:
每次调用 createObjectURL() 时,都会创建一个新的对象 URL,即使您已经为同一个对象创建了一个 URL。当您不再需要它们时,必须通过调用 URL.revokeObjectURL() 来释放它们中的每一个。当文档被卸载时,浏览器会自动释放它们;但是,为了获得最佳性能和内存使用,如果您可以在安全时间显式卸载它们,则应该这样做。
Failed: network error
。这个效果很好。
const url = URL.createObjectURL(blob, { oneTimeOnly: true })
。如果需要,您可以随时保存 blob 并在以后生成新的 Url。
document.body.appendChild(elem);
之前添加 elem.style.display = 'none';
上述所有示例在 chrome 和 IE 中都可以正常工作,但在 Firefox 中失败。请考虑在主体上附加一个锚点并在单击后将其移除。
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob(['Test,Text'], {type: 'text/csv'}));
a.download = 'test.csv';
// Append anchor to body.
document.body.appendChild(a);
a.click();
// Remove anchor from body
document.body.removeChild(a);
a.click()
行上抛出“访问被拒绝”,因为它认为 blob URL 是跨域的。
我很高兴使用 FileSaver.js。它的兼容性很好(IE10+和其他),而且使用起来非常简单:
var blob = new Blob(["some text"], {
type: "text/plain;charset=utf-8;",
});
saveAs(blob, "thing.txt");
<a>
上相当新的 download attribute。
以下方法适用于 IE11+、Firefox 25+ 和 Chrome 30+:
<a id="export" class="myButton" download="" href="#">export</a>
<script>
function createDownloadLink(anchorSelector, str, fileName){
if(window.navigator.msSaveOrOpenBlob) {
var fileData = [str];
blobObject = new Blob(fileData);
$(anchorSelector).click(function(){
window.navigator.msSaveOrOpenBlob(blobObject, fileName);
});
} else {
var url = "data:text/plain;charset=utf-8," + encodeURIComponent(str);
$(anchorSelector).attr("download", fileName);
$(anchorSelector).attr("href", url);
}
}
$(function () {
var str = "hi,file";
createDownloadLink("#export",str,"file.txt");
});
</script>
实际操作:http://jsfiddle.net/Kg7eA/
Firefox 和 Chrome 支持导航的数据 URI,它允许我们通过导航到数据 URI 来创建文件,而 IE 出于安全目的不支持它。
另一方面,IE 有用于保存 blob 的 API,可用于创建和下载文件。
github.com/kennethjiang/js-file-download 中的包 js-file-download 处理浏览器支持的边缘情况:
View source 了解它如何使用本页中提到的技术。
安装
yarn add js-file-download
npm install --save js-file-download
用法
import fileDownload from 'js-file-download'
// fileDownload(data, filename, mime)
// mime is optional
fileDownload(data, 'filename.csv', 'text/csv')
我们可以使用 URL api,特别是 URL.createObjectURL() 和 Blob api 来编码和下载几乎任何东西。
如果您的下载量很小,这可以正常工作:
document.body.innerHTML += `点击我` download.click() download.outerHTML = ""
如果你的下载量很大,最好不要使用 DOM,而是使用下载参数创建一个链接元素,然后触发点击。
请注意,链接元素并未附加到文档中,但点击仍然有效!这样可以创建数百个 Mo 的下载,因为 DOM 没有被修改(否则 DOM 中的巨大 URL 可能是选项卡冻结的来源)。
const stack = { some: "stuffs", alot: "of them!" } BUTTONDOWNLOAD.onclick = (function(){ let j = document.createElement("a") j.download = "stack_"+Date.now()+".json" j.href = URL.createObjectURL(new Blob( [JSON.stringify(stack, null, 2)])) j.click() })
奖励!下载任何 cyclic objects,避免错误:
TypeError:循环对象值(Firefox) TypeError:将循环结构转换为 JSON(Chrome 和 Opera) TypeError:不支持值参数中的循环引用(Edge)
使用 https://github.com/douglascrockford/JSON-js/blob/master/cycle.js
在此示例中,将 document
对象下载为 json。
/* JSON.decycle */ if(typeof JSON.decycle!=="function"){JSON.decycle=function decycle(object,replacer){"use strict";var objects=new WeakMap();return(function derez (value,path){var old_path;var nu;if(replacer!==undefined){value=replacer(value)} if(typeof value==="object"&&value!==null&&!(value instanceof Boolean)&& !(value instanceof Date)&&!(value instanceof Number)&&!(value instanceof RegExp)&&!(value instanceof String)){old_path=objects.get(value);if(old_path!==undefined){return{$ ref:old_path}} objects.set(value,path);if(Array.isArray(value)){nu=[];value.forEach(function(element,i){nu[i]=derez(element,path+ "["+i+"]")})}else{nu={};Object.keys(value).forEach(function(name){nu[name]=derez(value[name],path+"["+ JSON.stringify(name)+"]")})} return nu} return value}(object,"$"))}} document.body.innerHTML += `` download.click()
此解决方案直接从 tiddlywiki 的 (tiddlywiki.com) github 存储库中提取。我几乎在所有浏览器中都使用过 tiddlywiki,它的工作原理就像一个魅力:
function(filename,text){
// Set up the link
var link = document.createElement("a");
link.setAttribute("target","_blank");
if(Blob !== undefined) {
var blob = new Blob([text], {type: "text/plain"});
link.setAttribute("href", URL.createObjectURL(blob));
} else {
link.setAttribute("href","data:text/plain," + encodeURIComponent(text));
}
link.setAttribute("download",filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
Github 存储库:Download saver module
使用 Blob:
function download(content, mimeType, filename){
const a = document.createElement('a') // Create "a" element
const blob = new Blob([content], {type: mimeType}) // Create a blob (file-like object)
const url = URL.createObjectURL(blob) // Create an object URL from blob
a.setAttribute('href', url) // Set "a" element link
a.setAttribute('download', filename) // Set download filename
a.click() // Start downloading
}
所有现代浏览器都支持 Blob。 Blob 的 Caniuse 支持表:
这里MDN Docs
如果您只想将字符串转换为可供下载,您可以使用 jQuery 尝试此操作。
$('a.download').attr('href', 'data:application/csv;charset=utf-8,' + encodeURI(data));
适用于 IE10 的解决方案:(我需要一个 csv 文件,但将类型和文件名更改为 txt 就足够了)
var csvContent=data; //here we load our csv data
var blob = new Blob([csvContent],{
type: "text/csv;charset=utf-8;"
});
navigator.msSaveBlob(blob, "filename.csv")
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
// Start file download.
download("hello.txt","This is the content of my file :)");
如前所述,filesaver 是在客户端处理文件的绝佳软件包。但是,它不适用于大文件。 StreamSaver.js 是可以处理大文件的替代解决方案(在 FileServer.js 中指出):
const fileStream = streamSaver.createWriteStream('filename.txt', size);
const writer = fileStream.getWriter();
for(var i = 0; i < 100; i++){
var uint8array = new TextEncoder("utf-8").encode("Plain Text");
writer.write(uint8array);
}
writer.close()
var element = document.createElement('a');
element.setAttribute('href', 'data:text/text;charset=utf-8,' + encodeURI(data));
element.setAttribute('download', "fileName.txt");
element.click();
基于@Rick 的回答,这真的很有帮助。
如果您想以这种方式共享它,则必须对字符串 data
进行转义:
$('a.download').attr('href', 'data:application/csv;charset=utf-8,'+ encodeURI(data));
` 抱歉,由于我目前在 StackOverflow 中的声誉很低,我无法对 @Rick 的回答发表评论。
edit suggestion 已共享并被拒绝。
以下功能有效。
private createDownloadableCsvFile(fileName, content) {
let link = document.createElement("a");
link.download = fileName;
link.href = `data:application/octet-stream,${content}`;
return link;
}
以下方法适用于 IE10+、Edge、Opera、FF 和 Chrome:
const saveDownloadedData = (fileName, data) => {
if(~navigator.userAgent.indexOf('MSIE') || ~navigator.appVersion.indexOf('Trident/')) { /* IE9-11 */
const blob = new Blob([data], { type: 'text/csv;charset=utf-8;' });
navigator.msSaveBlob(blob, fileName);
} else {
const link = document.createElement('a')
link.setAttribute('target', '_blank');
if(Blob !== undefined) {
const blob = new Blob([data], { type: 'text/plain' });
link.setAttribute('href', URL.createObjectURL(blob));
} else {
link.setAttribute('href', 'data:text/plain,' + encodeURIComponent(data));
}
~window.navigator.userAgent.indexOf('Edge')
&& (fileName = fileName.replace(/[&\/\\#,+$~%.'':*?<>{}]/g, '_')); /* Edge */
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
所以,只需调用函数:
saveDownloadedData('test.txt', 'Lorem ipsum');
对我来说,这非常有效,下载了相同的文件名和扩展名
<a href={"data:application/octet-stream;charset=utf-16le;base64," + file64 } download={title} >{title}</a>
'title' 是带有扩展名的文件名,即 sample.pdf
、waterfall.jpg
等。
'file64' 是类似这样的 base64 内容,即 Ww6IDEwNDAsIFNsaWRpbmdTY2FsZUdyb3VwOiAiR3JvdXAgQiIsIE1lZGljYWxWaXNpdEZsYXRGZWU6IDM1LCBEZW50YWxQYXltZW50UGVyY2VudGFnZTogMjUsIFByb2NlZHVyZVBlcmNlbnQ6IDcwLKCFfSB7IkdyYW5kVG90YWwiOjEwNDAsIlNsaWRpbmdTY2FsZUdyb3VwIjoiR3JvdXAgQiIsIk1lZGljYWxWaXNpdEZsYXRGZWUiOjM1LCJEZW50YWxQYXltZW50UGVyY2VudGFnZSI6MjUsIlByb2NlZHVyZVBlcmNlbnQiOjcwLCJDcmVhdGVkX0J5IjoiVGVycnkgTGVlIiwiUGF0aWVudExpc3QiOlt7IlBhdGllbnRO
我会使用 <a></a>
标记,然后设置 href='path'
。然后,在 <a>
元素之间放置一个图像,以便我可以直观地看到它。如果您愿意,您可以创建一个更改 href
的函数,使其不仅是同一个链接,而且是动态的。
如果您想使用 javascript 访问 <a>
标记,也请给它一个 id
。
从 HTML 版本开始:
<a href="mp3/tupac_shakur-how-do-you-want-it.mp3" download id="mp3Anchor">
<img src="some image that you want" alt="some description" width="100px" height="100px" />
</a>
现在使用 JavaScript:
*Create a small json file*;
const array = [
"mp3/tupac_shakur-how-do-you-want-it.mp3",
"mp3/spice_one-born-to-die.mp3",
"mp3/captain_planet_theme_song.mp3",
"mp3/tenchu-intro.mp3",
"mp3/resident_evil_nemesis-intro-theme.mp3"
];
//load this function on window
window.addEventListener("load", downloadList);
//now create a function that will change the content of the href with every click
function downloadList() {
var changeHref=document.getElementById("mp3Anchor");
var j = -1;
changeHref.addEventListener("click", ()=> {
if(j < array.length-1) {
j +=1;
changeHref.href=""+array[j];
}
else {
alert("No more content to download");
}
}
在示例中下载带扩展名或不带扩展名的文件,我使用的是 JSON。您可以添加您的数据和扩展。您可以根据自己的意愿在此处使用“MAC-Addresses.json”。如果要添加扩展名,请在此处添加,否则,只需写入不带扩展名的文件名。
let myJson = JSON.stringify(yourdata);
let element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(myJson));
element.setAttribute('download', 'MAC-Addresses.json');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
如果文件包含文本数据,我使用的一种技术是将文本放入 textarea 元素并让用户选择它(单击 textarea,然后按 ctrl-A)然后复制,然后粘贴到文本编辑器。
不定期副业成功案例分享
download
属性,您可以指定文件名 ;-)txt
扩展名。如果您执行download("data.json", data)
,它将按预期工作。