2013-09-06 2 views
1

보기에 표시된 표의 내용을 CSV 파일로 다운로드해야합니다. .csv 파일로 저장할 수 있도록 테이블의 내용을 제대로 형식화하는 코드가 있습니다 (예 : 열 구분 기호는 쉼표로, 테이블의 각 레코드는 새 행에 있음).길이가 긴 데이터를 CSV 파일로 다운로드

window.location.href = '/download?data=' + encodeURIComponent($scope.csvString); 

내가 서버 부분에 대한 NodeJs을 사용하고 있습니다 :

그래서, 내 컨트롤러, 나는 다음과 같은 코드가 있습니다. 여기에 다음과 같은 경로 처리기가 있습니다.

app.get('/download', function (req, res) { 
    var data = req.query.data; 

    res.attachment('data.csv'); 
    res.setHeader('Content-Type', 'text/csv'); 
    res.end(data); 
}); 

이것은 완벽하게 작동합니다. 다운로드가 작동하고 다운로드 한 파일의 데이터가 완벽한 CSV 형식입니다. 문제 없음.

테이블에 너무 많은 레코드가있을 때, 즉 데이터가 큰 경우 문제가 발생합니다. 이 때문에 쿼리 매개 변수가 정말 커지고 한계를 초과하므로 GET 요청이 400 (잘못된 요청) 오류와 함께 반환된다고 가정합니다. 분석 결과 요청은 서버에 도달하지 않고 요청이 Chrome 개발자 도구를 사용하지 못했습니다. 브라우저에서 URL은 간단히 www.my_domain.com/download?data=the_lengthy_data입니다. 그게 전부 야. 웹 페이지가 비어 있거나 비어 있고 파일이 다운로드되지 않습니다.

따라서 긴 데이터를 어떻게 다운로드 할 수 있는지 알고 싶습니다. 내가 만난 모든 예제는 GET 요청을하므로 긴 데이터를 쿼리 매개 변수로 전달해야합니다. 다른 접근법이 있습니까?

+0

서버로 전송 된 프런트 엔드에서 생성 된 CSV 데이터 만 클라이언트로 다시 다운로드 할 수 있습니까? –

+0

@SalehenRahman 네 이해가 정확합니다. – callmekatootie

답변

5

질문에 대한 답변이 아니지만 모양에서 보면 클라이언트에서 생성 된 데이터 다운로드를 강제로 시도하고 있습니다. 그런 다음이 경우 직접 데이터가 포함 된 데이터 URI를 만들 수 있습니다.

귀하의 각도 JS 템플릿 :

<a href="data:base64,{{btoa(csvString)}}" download>Download CSV</a> 

컨트롤러 : 결과

$scope.btoa = function (val) { 
    return btoa(val); 
}; 

, 당신의 DOM이 같아야합니다 :

<!-- The link contains data to the CSV string "a,b,c" --> 
<a href="data:text/csv;base64,YSxiLGM=" download>Download CSV</a> 

그리고 링크를 클릭하면 CSV 다운로드 파일.

또한 라이브러리를 사용하여 문자열의 다운로드를 강제 할 수

편집 FileSaver.js을했다.

평소와 마찬가지로 CSV를 얻을 수 있지만 이번에는 BLOB로 변환합니다.

var csvBlob = new Blob([$scope.csvString], { type: 'text/csv;charset=utf-8' }); 

그리고, 당신은 FileSaver.js 'saveAs 함수를 호출 할 수 있습니다.

saveAs(csvBlob, 'mydata.csv'); 
+0

저는 AngularJS에 100 % 익숙하지 않습니다. 나는 당신이''data : text/csv; base64, '+ btoa ($ scope.csvString)'와 같도록'$ scope'의'href' 값을 설정한다고 생각 하겠지만, 나는 100 % 확실하지 않습니다. –

+0

답을 업데이트했습니다. 나는 그 트릭을해야한다고 생각해. –

0

You're right about the character limit in the URL. 일반적으로 길이가 긴 데이터는 본문에 전달됩니다. 이론적으로이 데이터는 이론상 문자 제한이 없으므로 전달됩니다.

그러나 GET 요청에서 본문을 전달하지 마십시오. The XMLHttpRequest specs on the send method say - "요청 방법이 GET 또는 HEAD 인 경우 데이터를 null로 설정하십시오."

POST 요청을 사용하고 본문에 매개 변수를 전달하는 것이 좋습니다. 따라서 app.post ('download', ...)를 사용하여 핸들러를 다시 작성한 다음 해당 매개 변수에 대한 request.body를 파싱해야합니다.

또한 내 이해에 따르면 서버가 처리하고 다시 전달할 데이터 블록을 제공 할 때 POST가 더 적합한 HTTP 동사처럼 보입니다.

+0

게시를 시도했습니다. 그러나 다운로드가 발생하지 않습니다. 할 일이 있습니까? GET이 POST이고 데이터가 POST 요청의 본문에 전달되는 것을 제외하면 코드는 이전과 동일합니다 ... – callmekatootie

+0

body 파서를 사용하고 있습니까? app.use (express.bodyParser()); 그런 다음 req.body를 사용할 수 있습니다. –

+0

예, 본문 파서를 사용하고 있습니다 ... – callmekatootie

0

아래와 같이 nodejs 코드를 변경해야합니다. Nodejs 코드

function downloadableFile(req, res) { 
     res.attachment(document.title); 
     var bufferStream = new stream.PassThrough(); 
     // we read the file in buffer. 
     bufferStream.end(new Buffer(document.buffer)); 
     return bufferStream.pipe(res); 
    } 

Angularjs는 이진 데이터를 인식하지 못합니다. 프론트 엔드에서는 FileSaver.js와 같은 타사 도구를 사용할 수 있습니다.

var csvBlob = new Blob ([$ scope.csvString], {type : 'text/csv; charset = utf-8'}); saveAs (csvBlob, 'mydata.csv');

또는 이와 같은 angularjs 코드를 사용할 수 있습니다. Angularjs 코드.

downloadDocument = function (path,id,type) { 

    $http.get(path).then(function (data) { 
    if (data.status === 404) { 
     mpToastService.showToastHeader('error', 'Error downloading document'); 
    } else { 
     var blob = new Blob([data.data],{ 
     type: type + ";charset=utf-8;" 
     }); 
     $("#" + id).attr("href", window.URL.createObjectURL(blob)); 
     document.getElementById(id).click(); 
    } 
    }); 
    }  

    //In html file, we need to include these two lines. 

    <a ng-click="downloadDocument(document.path,document.id,document.mimeType)" >document.title</a>  
    <a id="document.id"></a> 

이 각 코드는 전단에 바이너리 데이터를 다운로드하고 다음 인기있는 브라우저에서 모든 데이터 제한없이 다운로드 모달 팝업. 그러나 일반적으로 이는 클라이언트 특별 요구 사항을 제외하고는 좋은 습관이 아닙니다.

관련 문제