source

사용자가 다운로드 할 수 있는 메모리 내에 파일을 작성하는 방법(서버 경유는 아님)

goodcode 2022. 9. 12. 11:39
반응형

사용자가 다운로드 할 수 있는 메모리 내에 파일을 작성하는 방법(서버 경유는 아님)

서버와의 대화 없이 클라이언트 측에서 텍스트 파일을 생성하여 사용자에게 다운로드하도록 지시할 수 있는 방법이 있습니까?컴퓨터(보안 등)에 직접 쓸 수 없지만 작성 및 저장 여부를 확인할 수 있습니까?

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!');

데이터 URI 를 사용할 수 있습니다.브라우저 지원은 다양합니다.Wikipedia 를 참조해 주세요.예:

<a href="data:application/octet-stream;charset=utf-16le;base64,//5mAG8AbwAgAGIAYQByAAoA">text file</a>

octet-stream은 다운로드 프롬프트를 강제합니다.그렇지 않으면 브라우저에서 열립니다.

CSV의 경우 다음 항목을 사용할 수 있습니다.

<a href="data:application/octet-stream,field1%2Cfield2%0Afoo%2Cbar%0Agoo%2Cgai%0A">CSV Octet</a>

jsFiddle 데모를 사용해 보십시오.

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);
    }
}

상황에 따라서는 URL.revoke Object를 호출할 수도 있습니다.삭제 후 URLelemURL.createObject 문서에 따르면URL:

createObjectURL()을 호출할 때마다 동일한 오브젝트에 대해 이미 작성한 경우에도 새로운 오브젝트 URL이 생성됩니다.이들 각각은 필요 없게 되었을 때 URL.revokeObjectURL()을 호출하여 해방해야 합니다.브라우저는 문서가 언로드될 때 자동으로 릴리스되지만 최적의 성능과 메모리 사용을 위해 언로드할 수 있는 안전 시간이 있는 경우 이 작업을 수행해야 합니다.

위의 예는 모두 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);

FileSaver.js를 즐겁게 사용하고 있습니다.호환성은 매우 우수하며(IE10+ 및 기타 모든 것), 사용법은 매우 간단합니다.

var blob = new Blob(["some text"], {
    type: "text/plain;charset=utf-8;",
});
saveAs(blob, "thing.txt");

다음 방법은 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-display는 브라우저 지원을 위한 엣지 케이스를 처리합니다.

소스를 보고 이 페이지에 언급된 기술을 어떻게 사용하는지 확인하십시오.

인스톨

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 += 
`<a id="download" download="PATTERN.json" href="${URL.createObjectURL(new Blob([JSON.stringify("HELLO WORLD", null, 2)]))}"> Click me</a>`
download.click()
download.outerHTML = ""


다운로드가 큰 경우 DOM을 사용하는 대신 다운로드 매개 변수를 사용하여 링크 요소를 만들고 클릭을 트리거하는 것이 좋습니다.

링크 요소는 문서에 추가되지 않지만 클릭은 작동합니다!이렇게 하면 DOM은 변경되지 않기 때문에 수백 개의 Mo를 다운로드 할 수 있습니다(그렇지 않으면 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()
})
<button id="BUTTONDOWNLOAD">DOWNLOAD!</button>


보너스! 모든 주기 개체를 다운로드하여 오류를 방지합니다.

TypeError: 순환 개체 값(Firefox) TypeError: 변환 중

순환 구조에서 JSON(Chrome and Opera) 유형 오류: 순환

값 인수의 참조는 지원되지 않습니다(Edge).

https://github.com/douglascrockford/JSON-js/blob/master/cycle.js 사용방법

예에서는, 「Downloading the Download」(다운로드)를 하고 있습니다.documentjson으로

/* 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()

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:

여기 바이올린이 있습니다.

여기 MDN 문서

이 솔루션은 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 repo:다운로드 세이버 모듈

다운로드할 수 있도록 문자열을 변환하려는 경우 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 :)");

기사 원문 : https://ourcodeworld.com/articles/read/189/how-to-create-a-file-and-generate-a-download-with-javascript-in-the-browser-without-a-server

앞에서 설명한 바와 같이 파일세이버는 클라이언트 측에서 파일을 조작하기 위한 훌륭한 패키지입니다.하지만 큰 파일에서는 잘 되지 않습니다.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의 답변에 대해 코멘트를 할 수 없습니다.

편집 제안이 공유되었지만 거부되었습니다.

이 기능은 동작했습니다.

 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>

'filename'은 확장자를 가진 파일 이름입니다.sample.pdf,waterfall.jpg

'file64'는 다음과 같은 base64 콘텐츠입니다.Ww6IDEwNDAsIFNsaWRpbmdTY2FsZUdyb3VwOiAiR3JvdXAgQiIsIE1lZGljYWxWaXNpdEZsYXRGZWU6IDM1LCBEZW50YWxQYXltZW50UGVyY2VudGFnZTogMjUsIFByb2NlZHVyZVBlcmNlbnQ6IDcwLKCFfSB7IkdyYW5kVG90YWwiOjEwNDAsIlNsaWRpbmdTY2FsZUdyb3VwIjoiR3JvdXAgQiIsIk1lZGljYWxWaXNpdEZsYXRGZWUiOjM1LCJEZW50YWxQYXltZW50UGVyY2VudGFnZSI6MjUsIlByb2NlZHVyZVBlcmNlbnQiOjcwLCJDcmVhdGVkX0J5IjoiVGVycnkgTGVlIiwiUGF0aWVudExpc3QiOlt7IlBhdGllbnRO

이 경우,<a></a>태그 붙이고 나서href='path'그 후, 그 사이에 이미지를 배치합니다.<a>시각적으로 볼 수 있게 하는 거죠.필요에 따라서, 다음의 기능을 변경할 수 있습니다.href같은 링크일 뿐만 아니라 다이내믹하게 할 수 있도록 하겠습니다.

를 제공하다<a>꼬리표를 달다idjavascript로 접속하고 싶은 경우에도 마찬가지입니다.

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 를 사용할 수 있습니다.네 소원대로 여기 있어확장자를 추가하려면 여기에 추가하고 그렇지 않으면 파일 이름을 확장자 없이 작성하십시오.

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);

파일에 텍스트 데이터가 포함되어 있는 경우 텍스트 영역 요소에 텍스트를 넣고 사용자가 선택하도록 한 다음(텍스트 영역을 클릭한 다음 Ctrl+A를 클릭) 복사한 후 텍스트 편집기에 붙여넣는 방법을 사용합니다.

언급URL : https://stackoverflow.com/questions/3665115/how-to-create-a-file-in-memory-for-user-to-download-but-not-through-server

반응형