web-dev-qa-db-fra.com

Javascript - Télécharger CSV en tant que fichier

Je joue avec du javascript pour télécharger du texte csv:

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

Jusqu'à présent, cela fonctionne, mais comme le navigateur m'invite à enregistrer le fichier, il n'y a pas de nom de fichier, ni d'extension.

Comment puis-je prédéterminer le nom du fichier et son extension, à l'intérieur du window.location.href?

16
coffeemonitor
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/

18
Andrew

Dans mon cas, il s'est avéré qu'Excel a ignoré la partie charset = UTF-8. J'ai trouvé une solution dans ce post , pour forcer Excel à prendre en compte l'UTF-8. Donc cette dernière ligne a fait l'affaire pour moi:

downloadFile('2.csv', 'data:text/csv;charset=UTF-8,' + '\uFEFF' + encodeURIComponent(data));
13
user1826063

Mise à jour Réponse d'Andrew pour éviter d'utiliser une fonction obsolète.

source: 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));
7
Jeff Sallans

En réponse aux réponses précédentes, Mozilla Firefox et Google Chrome ne vous permettent plus de rediriger la fenêtre principale vers un URI de données. Pour contourner ce problème, vous pouvez créer un iframe et un élément a qui redirigera cet élément iframe vers votre URI de données. Voici un exemple de code qui fera l'affaire.

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>

Notez que si vous décidez d'utiliser jQuery, vous devez toujours utiliser la fonction de clic native —$("a#linkDownload")[0].click() au lieu de simplement $("a#linkDownload").click().

1
Paul Rowe