사용자가 다운로드 할 수 있도록 메모리에 파일을 생성하는 방법은 무엇입니까?
서버와의 상호 작용없이 클라이언트 측에서 텍스트 파일을 만들고 사용자에게 다운로드하라는 메시지를 표시 할 수있는 방법이 있습니까? 나는 그들의 컴퓨터 (보안 및 모든 것)에 직접 쓸 수 없다는 것을 알고 있지만, 그들을 만들고 저장하라는 메시지를 표시 할 수 있습니까?
데이터 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 데모를 사용해보십시오 .
HTML5 지원 브라우저를위한 간단한 솔루션 ...
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);
}
form * {
display: block;
margin: 10px;
}
<form onsubmit="download(this['name'].value, this['text'].value)">
<input type="text" name="name" value="test.txt">
<textarea name="text"></textarea>
<input type="submit" value="Download">
</form>
용법
download('test.txt', 'Hello world!');
위의 모든 솔루션이 모든 브라우저에서 작동하지 않았습니다. 다음은 IE 10+, Firefox 및 Chrome에서 마지막으로 작동하는 것입니다 ( jQuery 또는 다른 라이브러리 없이 ).
save: function(filename, data) {
var blob = new Blob([data], {type: 'text/csv'});
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
}
else{
var elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = filename;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
}
Note that, depending on your situation, you may also want to call URL.revokeObjectURL after removing elem
. According to the docs for URL.createObjectURL:
Each time you call createObjectURL(), a new object URL is created, even if you've already created one for the same object. Each of these must be released by calling URL.revokeObjectURL() when you no longer need them. Browsers will release these automatically when the document is unloaded; however, for optimal performance and memory usage, if there are safe times when you can explicitly unload them, you should do so.
All of the above example works just fine in chrome and IE, but fail in Firefox. Please do consider appending an anchor to the body and removing it after click.
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);
I'm happily using FileSaver.js. Its compatibility is pretty good (IE10+ and everything else), and it's very simple to use:
var blob = new Blob(["some text"], {
type: "text/plain;charset=utf-8;",
});
saveAs(blob, "thing.txt");
The following method works in IE11+, Firefox 25+ and 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>
See this in Action: http://jsfiddle.net/Kg7eA/
Firefox and Chrome support data URI for navigation, which allows us to create files by navigating to a data URI, while IE doesn't support it for security purposes.
On the other hand, IE has API for saving a blob, which can be used to create and download files.
This solution is extracted directly from tiddlywiki's (tiddlywiki.com) github repository. I have used tiddlywiki in almost all browsers and it works like a charm:
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 repo: Download saver module
Solution that work on IE10: (I needed a csv file, but it's enough to change type and filename to 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")
If you just want to convert a string to be available for download you can try this using jQuery.
$('a.download').attr('href', 'data:application/csv;charset=utf-8,' + encodeURI(data));
var element = document.createElement('a');
element.setAttribute('href', 'data:text/text;charset=utf-8,' + encodeURI(data));
element.setAttribute('download', "fileName.txt");
element.click();
As mentioned before, filesaver is a great package to work with files on the client side. But, it is not do well with large files. StreamSaver.js is an alternative solution (which is pointed in FileServer.js) that can handle large files:
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()
The package js-file-download from github.com/kennethjiang/js-file-download handles edge cases for browser support:
View source to see how it uses techniques mentioned on this page.
Installation
yarn add js-file-download
npm install --save js-file-download
Usage
import fileDownload from 'js-file-download'
// fileDownload(data, filename, mime)
// mime is optional
fileDownload(data, 'filename.csv', 'text/csv')
As of April 2014, FileSytem APIs may not be standardized in W3C. Anyone looking at the solution with blob should thread with caution, I guess.
W3C Mailing List on FileSytem API
Based on @Rick answer which was really helpful.
You have to scape the string data
if you want to share it this way:
$('a.download').attr('href', 'data:application/csv;charset=utf-8,'+ encodeURI(data));
` Sorry I can not comment on @Rick's answer due to my current low reputation in StackOverflow.
An edit suggestion was shared and rejected.
You can even do one better than just URI's - using Chrome you are also able to suggest the name the file will take, as explained in this blog post about naming a download when using URIs.
This below function worked.
private createDownloadableCsvFile(fileName, content) {
let link = document.createElement("a");
link.download = fileName;
link.href = `data:application/octet-stream,${content}`;
return link;
}
For me this worked perfectly, with the same filename and extension getting downloaded
<a href={"data:application/octet-stream;charset=utf-16le;base64," + file64 } download={title} >{title}</a>
'title' is the file name with extension i.e, sample.pdf
, waterfall.jpg
, etc..
'file64' is the base64 content something like this i.e, Ww6IDEwNDAsIFNsaWRpbmdTY2FsZUdyb3VwOiAiR3JvdXAgQiIsIE1lZGljYWxWaXNpdEZsYXRGZWU6IDM1LCBEZW50YWxQYXltZW50UGVyY2VudGFnZTogMjUsIFByb2NlZHVyZVBlcmNlbnQ6IDcwLKCFfSB7IkdyYW5kVG90YWwiOjEwNDAsIlNsaWRpbmdTY2FsZUdyb3VwIjoiR3JvdXAgQiIsIk1lZGljYWxWaXNpdEZsYXRGZWUiOjM1LCJEZW50YWxQYXltZW50UGVyY2VudGFnZSI6MjUsIlByb2NlZHVyZVBlcmNlbnQiOjcwLCJDcmVhdGVkX0J5IjoiVGVycnkgTGVlIiwiUGF0aWVudExpc3QiOlt7IlBhdGllbnRO
We can use the URL api, in particular URL.createObjectURL(), and the Blob api to encode and download pretty much anything.
document.body.innerHTML +=
`<a id="download" download="PATTERN.json" href="${URL.createObjectURL(new Blob([JSON.stringify("HELLO WORLD", null, 2)]))}"> Click me</a>`
download.click()
download.outerHTML = ""
Bonus! Download any cyclic objects, avoid the errors:
TypeError: cyclic object value (Firefox) TypeError: Converting
circular structure to JSON (Chrome and Opera) TypeError: Circular
reference in value argument not supported (Edge)
Using https://github.com/douglascrockford/JSON-js/blob/master/cycle.js
/* 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 +=
`<a id="download" download="PATTERN.json" href="${URL.createObjectURL(new Blob([JSON.stringify(JSON.decycle(document), null, 2)]))}"></a>`
download.click()
If the file contains text data, a technique I use is to put the text into a textarea element and have the user select it (click in textarea then ctrl-A) then copy followed by a paste to a text editor.
'development' 카테고리의 다른 글
항목이 JavaScript 배열에 있는지 확인하는 가장 좋은 방법은 무엇입니까? (0) | 2020.09.29 |
---|---|
PHP에서 작은 따옴표와 큰 따옴표 문자열의 차이점은 무엇입니까? (0) | 2020.09.29 |
JavaScript에서 DOM 노드의 모든 자식 요소 제거 (0) | 2020.09.29 |
ls를 사용하여 디렉토리 및 전체 크기 나열 (0) | 2020.09.29 |
Java의 데몬 스레드는 무엇입니까? (0) | 2020.09.29 |