web-dev-qa-db-fra.com

Écrire dans un fichier CSV et l'exporter?

Dans C # ASP.net, quelqu'un pourrait-il me montrer comment je peux écrire des entrées à partir d'un tableau/liste dans un fichier CSV sur le serveur, puis ouvrir le fichier? Je pense que la deuxième partie serait quelque chose comme - Response.Redirect (" http://myserver.com/file.csv "), mais je ne sais pas comment écrire le fichier sur le serveur.

De plus, si cette page est consultée par de nombreux utilisateurs, est-il préférable de générer un nouveau fichier CSV à chaque fois ou d'écraser le même fichier? Y aurait-il des problèmes de lecture/écriture/verrouillage si les deux utilisateurs essayaient d'accéder au même fichier CSV, etc.?


Mise à jour:

C'est probablement une question stupide et j'ai cherché sur Google, mais je ne trouve pas de réponse définitive - comment écrire un fichier CSV sur le serveur Web et l'exporter en C # ASP.net? Je sais comment le générer mais je voudrais le sauvegarder sur www.mysite.com/my.csv puis l'exporter.

25
Romulus

Rom, tu te trompes. Vous ne voulez pas écrire de fichiers sur le disque pour que IIS puisse les servir. Cela ajoute des implications de sécurité et augmente la complexité. Tout ce que vous devez vraiment faire est d'enregistrer le CSV directement dans le flux de réponse.

Voici le scénario: l'utilisateur souhaite télécharger csv. L'utilisateur soumet un formulaire avec des détails sur le csv qu'il souhaite. Vous préparez le csv, puis fournissez à l'utilisateur une URL vers une page aspx qui peut être utilisée pour construire le fichier csv et l'écrire dans le flux de réponse. L'utilisateur clique sur le lien. La page aspx est vierge; dans le code de page derrière vous, écrivez simplement le csv dans le flux de réponse et terminez-le.

Vous pouvez ajouter ce qui suit à l'événement (je pense que c'est correct) Load :

string attachment = "attachment; filename=MyCsvLol.csv";
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "text/csv";
HttpContext.Current.Response.AddHeader("Pragma", "public");

var sb = new StringBuilder();
foreach(var line in DataToExportToCSV)
  sb.AppendLine(TransformDataLineIntoCsv(line));

HttpContext.Current.Response.Write(sb.ToString());

écrire dans le code du flux de réponse ganked d'ici .

55
Will

Voici une classe CsvExport open-source gratuite très simple pour C #. Il y a un exemple ASP.NET MVC en bas.

https://github.com/jitbit/CsvExport

Il prend en charge les sauts de ligne, les virgules, les guillemets qui s'échappent, la compatibilité avec MS Excel ... Ajoutez simplement un court .cs fichier à votre projet et vous êtes prêt à partir.

(avertissement: je suis l'un des contributeurs)

25
Alex

Un commentaire sur la réponse de Will, vous voudrez peut-être remplacer HttpContext.Current.Response.End(); par HttpContext.Current.ApplicationInstance.CompleteRequest(); La raison en est que Response.End() lance un System.Threading.ThreadAbortException. Il abandonne un fil. Si vous avez un enregistreur d'exceptions, il sera jonché de ThreadAbortExceptions, qui dans ce cas est un comportement attendu.

Intuitivement, l'envoi d'un fichier CSV au navigateur ne devrait pas déclencher d'exception.

Voir ici pour plus Response.End () est-il considéré comme dangereux?

6
user2023861

Voici un résultat d'action CSV que j'ai écrit qui prend un DataTable et le convertit en CSV. Vous pouvez le renvoyer de votre vue et cela invitera l'utilisateur à télécharger le fichier. Vous devriez être en mesure de le convertir facilement en un formulaire compatible avec la liste ou même de simplement placer votre liste dans un DataTable.

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;

namespace Detectent.Analyze.ActionResults
{
    public class CSVResult : ActionResult
    {
        /// <summary>
        /// Converts the columns and rows from a data table into an Microsoft Excel compatible CSV file.
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="fileName">The full file name including the extension.</param>
        public CSVResult(DataTable dataTable, string fileName)
        {
            Table = dataTable;
            FileName = fileName;
        }

        public string FileName { get; protected set; }
        public DataTable Table { get; protected set; }




        public override void ExecuteResult(ControllerContext context)
        {
            StringBuilder csv = new StringBuilder(10 * Table.Rows.Count * Table.Columns.Count);

            for (int c = 0; c < Table.Columns.Count; c++)
            {
                if (c > 0)
                    csv.Append(",");
                DataColumn dc = Table.Columns[c];
                string columnTitleCleaned = CleanCSVString(dc.ColumnName);
                csv.Append(columnTitleCleaned);
            }
            csv.Append(Environment.NewLine);
            foreach (DataRow dr in Table.Rows)
            {
                StringBuilder csvRow = new StringBuilder();
                for(int c = 0; c < Table.Columns.Count; c++)
                {
                    if(c != 0)
                        csvRow.Append(",");

                    object columnValue = dr[c];
                    if (columnValue == null)
                        csvRow.Append("");
                    else
                    {
                        string columnStringValue = columnValue.ToString();


                        string cleanedColumnValue = CleanCSVString(columnStringValue);

                        if (columnValue.GetType() == typeof(string) && !columnStringValue.Contains(","))
                        {
                            cleanedColumnValue = "=" + cleanedColumnValue; // Prevents a number stored in a string from being shown as 8888E+24 in Excel. Example use is the AccountNum field in CI that looks like a number but is really a string.
                        }
                        csvRow.Append(cleanedColumnValue);
                    }
                }
                csv.AppendLine(csvRow.ToString());
            }

            HttpResponseBase response = context.HttpContext.Response;
            response.ContentType = "text/csv";
            response.AppendHeader("Content-Disposition", "attachment;filename=" + this.FileName);
            response.Write(csv.ToString());
        }

        protected string CleanCSVString(string input)
        {
            string output = "\"" + input.Replace("\"", "\"\"").Replace("\r\n", " ").Replace("\r", " ").Replace("\n", "") + "\"";
            return output;
        }
    }
}
5
Paul Mendoza

Comment écrire dans un fichier (recherche facile dans Google) ... 1er résultat de recherche

En ce qui concerne la création du fichier à chaque fois qu'un utilisateur accède à la page ... chaque accès agira en son propre nom. Votre analyse de rentabilisation dictera le comportement.

Cas 1 - même fichier mais ne change pas (ce type de cas peut avoir plusieurs façons d'être défini)

  • Vous auriez une logique qui a créé le fichier en cas de besoin et n'accédez au fichier que si la génération n'est pas nécessaire.

Cas 2 - chaque utilisateur doit générer son propre fichier

  • Vous décidez comment vous identifiez chaque utilisateur, créez un fichier pour chaque utilisateur et accédez au fichier qu'ils sont censés voir ... cela peut facilement fusionner avec le cas 1. Ensuite, vous supprimez le fichier après avoir servi le contenu ou non s'il nécessite de la persistance .

Cas 3 - même fichier mais génération requise pour chaque accès

  • Utilisez le cas 2, cela provoquera une génération à chaque fois mais sera nettoyé une fois accessible.
1
Jamie Altizer

consultez la bibliothèque csvreader/writer à http://www.codeproject.com/KB/cs/CsvReaderAndWriter.aspx

0
dankyy1