Javascript — скачать CSV как файл

Я возился с некоторым javascript, чтобы загрузить текст csv:

<script>
var data = '"Column One","Column Two","Column Three"';
window.location.href = 'data:text/csv;charset=UTF-8,' + encodeURIComponent(data);
</script>

Пока это работает, но когда браузер предлагает мне сохранить файл, нет ни имени файла, ни расширения.

Как я могу предопределить имя файла и его расширение внутри window.location.href ?


person coffeemonitor    schedule 17.01.2014    source источник
comment
В зависимости от вашего целевого клиента вы можете рассмотреть HTML5 download атрибут <a>.   -  person Passerby    schedule 17.01.2014


Ответы (4)


function downloadFile(fileName, urlData) {

    var aLink = document.createElement('a');
    var evt = document.createEvent("HTMLEvents");
    evt.initEvent("click");
    aLink.download = fileName;
    aLink.href = urlData;
    aLink.dispatchEvent(evt);
}

var data = '"Column One","Column Two","Column Three"';
downloadFile('2.csv', 'data:text/csv;charset=UTF-8,' + encodeURIComponent(data));

http://jsfiddle.net/rooseve/7bUG8/

person Andrew    schedule 17.01.2014
comment
Не забудьте .remove элемент. - person Yevgeniy Afanasyev; 29.04.2015
comment
@YevgeniyAfanasyev Можете ли вы дать больше объяснений и ссылок? - person caot; 20.09.2018

В моем случае оказалось, что Excel проигнорировал часть charset=UTF-8. В этом сообщении я нашел решение, чтобы заставить Excel учитывать учет UTF-8. Так что эта последняя строка помогла мне:

downloadFile('2.csv', 'data:text/csv;charset=UTF-8,' + '\uFEFF' + encodeURIComponent(data));
person user1826063    schedule 21.05.2014
comment
Большое спасибо, возможно, это не связано с вопросом, но это помогло мне в моей борьбе. - person Yevgeniy Afanasyev; 29.04.2015
comment
Это заканчивается тем, что файл обслуживается как UTF-8-DOM. - person M at; 06.10.2019

Обновлен Andrew Answer, чтобы избежать использования устаревшей функции.

источник: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events#The_old-fashioned_way

//Triggers a download of the given file
//@see https://stackoverflow.com/questions/21177078/javascript-download-csv-as-file
//@see https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events#The_old-fashioned_way
//
//@param fileName {string} - Name of the file to download include file extension
//@param urlData {string} - Encoded URI of the document data
function downloadFile(fileName, urlData) {

    var aLink = document.createElement('a');
    aLink.download = fileName;
    aLink.href = urlData;

    var event = new MouseEvent('click');
    aLink.dispatchEvent(event);
}

var data = '"Column One","Column Two","Column Three"';
downloadFile('2.csv', 'data:text/csv;charset=UTF-8,' + encodeURIComponent(data));
person Jeff Sallans    schedule 11.10.2016
comment
файл сохраняется с fileUrl(urlData) вместо fileName. - person S.Yadav; 31.05.2017

В ответ на предыдущие ответы Mozilla Firefox и Google Chrome больше не позволяют перенаправлять главное окно на URI данных. Чтобы обойти это, вы можете создать элемент iframe и элемент a, которые будут перенаправлять этот элемент iframe на ваш URI данных. Вот пример кода, который сделает свое дело.

function downloadTable(idTable) {
  function convertData() {
    function convertDataRow(elRow) {
      function convertDataCell(elCell) {
        return elCell.textContent.trim(); // Convert cell contents to plain text
      }
      var $cells = elRow.getElementsByTagName("td"); // Get all cells in this row
      // Convert the NodeList to an array and return an array of plain-text cell contents
      return Array.prototype.slice.call($cells).map(convertDataCell);
    }
    // Get all the rows in the table body
    var $rows = document.getElementById(idTable).querySelectorAll("tbody tr");
    // Convert the NodeList to an array and return an array of arrays with cell contents
    return Array.prototype.slice.call($rows).map(convertDataRow);
  }
  function convertHeaders() {
    function convertHeader(elHeader) {
      return elHeader.textContent.trim(); // Convert header contents to plain text.
    }
    // Get all headers in the table header
    var $headers = document.getElementById(idTable).querySelectorAll("thead th");
    // Convert the NodeList to an array and return an array of header contents.
    return Array.prototype.slice.call($headers).map(convertHeader);
  }
  function convertToCsv(data) {
    function convertCellToCsv(elData) {
      // Escape any quotes before returning the quoted string
      return "\"" + (elData || "").replace(/"/g, "\"\"") + "\"";
    }
    function convertRowToCsv(elRow) {
      // Return a comma-separated string of data values
      return elRow.map(convertCellToCsv).join(",");
    }
    // Return each row on its own line
    return data.map(convertRowToCsv).join("\n");
  }
  var csvToExport = convertToCsv([convertHeaders()].concat(convertData()));
  var dateNow = new Date();
  var timeStamp = (new Date(dateNow - dateNow.getTimezoneOffset() * 60000)) // Local time
    .toISOString() // Convert to ISO 8601 string
    .replace(/[^\d]/g, "-") // Turn anything that isn't a digit into a hyphen
    .replace(/-\d+-$/, ""); // Strip off the milliseconds
  var nameFile = "download-" + timeStamp + ".csv";
  if (navigator.msSaveBlob) { // Are we running this in IE?
    // Yes, we are running this in IE. Use IE-specific functionality.
    var blobExport = new Blob([csvToExport], { type: "text/csv;charset=utf-8," });
    navigator.msSaveBlob(blobExport, nameFile);
  } else {
    // No, we are not running this in IE. Use the iframe/link workaround.
    var urlData = "data:text/csv;charset=utf-8," + encodeURIComponent(csvToExport);
    // Create the iframe element and set up its attributes and styling
    var $iframe = document.createElement("iframe");
    $iframe.setAttribute("name", "iframe_download");
    $iframe.setAttribute("src", "about:blank");
    $iframe.style.visibility = "hidden";
    document.body.appendChild($iframe);
    // Create the a element and set up its attributes and styling.
    var $link = document.createElement("a");
    $link.setAttribute("download", nameFile);
    $link.setAttribute("href", urlData);
    // The target value should equal the iframe's name value.
    $link.setAttribute("target", "iframe_download");
    $link.style.visibility = "hidden";
    document.body.appendChild($link);
    // After the iframe loads, clean up the iframe and a elements.
    $iframe.addEventListener(
      "load",
      function () {
        document.body.removeChild($iframe);
        document.body.removeChild($link);
      }
    );
    $link.click(); // Send a click event to the link
  }
}
<table id="tableDownload" summary="Data to export">
  <thead>
    <tr>
      <th scope="col" style="text-align: left">Last Name</th>
      <th scope="col" style="text-align: left">First Name</th>
      <th scope="col" style="text-align: left">Street Address</th>
      <th scope="col" style="text-align: left">City</th>
      <th scope="col" style="text-align: left">State</th>
      <th scope="col" style="text-align: left">ZIP</th>
      <th scope="col" style="text-align: left">Phone</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Blackburn</td>
      <td>Mollie</td>
      <td>P.O. Box 620, 1873 Aliquet St.</td>
      <td>Waterbury</td>
      <td>CT</td>
      <td>99762</td>
      <td>1-318-946-6734</td>
    </tr>
    <tr>
      <td>Gamble</td>
      <td>Caleb</td>
      <td>8646 Aliquam Rd.</td>
      <td>Sacramento</td>
      <td>CA</td>
      <td>92800</td>
      <td>1-340-761-1459</td>
    </tr>
    <tr>
      <td>Mercer</td>
      <td>Keegan</td>
      <td>P.O. Box 454, 8858 Cursus Rd.</td>
      <td>Glendale</td>
      <td>AZ</td>
      <td>85590</td>
      <td>1-546-775-3600</td>
    </tr>
    <tr>
      <td>Lara</td>
      <td>Ethan</td>
      <td>575-5292 Egestas Rd.</td>
      <td>Denver</td>
      <td>CO</td>
      <td>21083</td>
      <td>1-830-500-3031</td>
    </tr>
    <tr>
      <td>Bennett</td>
      <td>Elmo</td>
      <td>P.O. Box 733, 6784 Magnis Ave</td>
      <td>Frankfort</td>
      <td>KY</td>
      <td>89835</td>
      <td>1-522-310-1841</td>
    </tr>
    <tr>
      <td>Dotson</td>
      <td>Stella</td>
      <td>132-2549 Eu Rd.</td>
      <td>Covington</td>
      <td>KY</td>
      <td>62519</td>
      <td>1-286-790-1404</td>
    </tr>
    <tr>
      <td>Malone</td>
      <td>Helen</td>
      <td>628 Gravida. St.</td>
      <td>Atlanta</td>
      <td>GA</td>
      <td>13271</td>
      <td>1-725-538-6018</td>
    </tr>
    <tr>
      <td>Lowe</td>
      <td>Macon</td>
      <td>Ap #445-9655 Velit Rd.</td>
      <td>Salem</td>
      <td>OR</td>
      <td>66270</td>
      <td>1-709-760-5241</td>
    </tr>
    <tr>
      <td>Haley</td>
      <td>Aileen</td>
      <td>833-1082 Duis Av.</td>
      <td>Southaven</td>
      <td>MS</td>
      <td>27019</td>
      <td>1-445-457-5467</td>
    </tr>
    <tr>
      <td>Riley</td>
      <td>Wade</td>
      <td>8270 Aliquam St.</td>
      <td>Grand Rapids</td>
      <td>MI</td>
      <td>95408</td>
      <td>1-254-595-8386</td>
    </tr>
  </tbody>
</table>
<button type="button" id="btnDownload" onclick="downloadTable('tableDownload')">Download Table</button>

Обратите внимание, что если вы решите использовать jQuery, вам все равно нужно использовать встроенную функцию щелчка $("a#linkDownload")[0].click() вместо простой $("a#linkDownload").click().

person Paul Rowe    schedule 13.05.2019