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 файл.

EDIT

Вы также можете вызвать загрузку строк с использованием библиотеки под названием FileSaver.js.

Как обычно, вы получите CSV, но на этот раз вы преобразуете его в BLOB.

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

И потом, вы можете вызвать функцию saveAs FileSaver.js'.

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

Я не на 100% знаком с AngularJS. Я бы предположил, что вы установили значение 'href'' $ scope' равным ''данным: text/csv; base64,' + btoa ($ scope.csvString)', но я не уверен на 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

Я пробовал POSTING. Однако загрузка не происходит. Есть ли что-нибудь еще? Код такой же, как и раньше, за исключением того, что GET теперь POST, и данные передаются в теле запроса POST ... – callmekatootie

+0

Используете ли вы парсер? app.use (express.bodyParser()); Тогда вы можете использовать req.body –

+0

Да, я использую body parser ... – 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> 

Этот угловой код будет загружать двоичные данные в передней части, а затем всплывал скачать модальность без каких-либо ограничений данных в популярных браузерах. Но в целом это не очень хорошая практика, за исключением особых требований клиента.

Смежные вопросы