web-dev-qa-db-ja.com

CSVファイルに書き込んでエクスポートしますか?

C#ASP.netで、配列/リストからサーバー上のCSVファイルにエントリを書き込み、そのファイルを開く方法を教えてもらえますか? 2番目の部分は-Response.Redirect( " http://myserver.com/file.csv ")のようなものになると思いますが、サーバーにファイルを書き込む方法がわかりません。

また、このページに多くのユーザーがアクセスする場合、毎回新しいCSVファイルを生成するか、同じファイルを上書きする方が良いでしょうか?両方のユーザーが同じCSVファイルなどにアクセスしようとした場合、読み取り/書き込み/ロックの問題はありますか?


更新:

これはおそらくばかげた質問であり、Googleで検索しましたが、明確な答えを見つけることができません-CSVファイルをWebサーバーに書き込んでC#ASP.netにエクスポートするにはどうすればよいですか?生成方法は知っていますが、www.mysite.com/my.csvに保存してからエクスポートしたいと思います。

25
Romulus

ロム、あなたは間違っている。 IISがファイルを提供できるようにファイルをディスクに書き込みたくない。これにより、セキュリティへの影響が増え、複雑さが増す。実際に行う必要があるのは、CSVを直接応答ストリーム。

シナリオは次のとおりです。ユーザーはcsvをダウンロードしたいと考えています。ユーザーは、希望するcsvに関する詳細を含むフォームを送信します。 csvを準備し、csvファイルを作成して応答ストリームに書き込むために使用できるaspxページへのURLをユーザーに提供します。ユーザーがリンクをクリックします。 aspxページは空白です。コードビハインドページで、csvを応答ストリームに書き込み、終了します。

(これは正しいと思います) 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());

応答ストリームコードへの書き込み ここから引用

55
Will

C#用の非常に簡単な無料のオープンソースCsvExportクラスを次に示します。下部にASP.NET MVCの例があります。

https://github.com/jitbit/CsvExport

改行、コンマ、引用符のエスケープ、MS Excelの互換性に注意します。1つの短い.csファイルをプロジェクトに追加すれば、準備完了です。

(免責事項:私は貢献者の一人です)

25
Alex

Willの答えに関するコメント。HttpContext.Current.Response.End();HttpContext.Current.ApplicationInstance.CompleteRequest();に置き換えたい場合があります。理由は、Response.End()System.Threading.ThreadAbortExceptionをスローするためです。スレッドを中止します。例外ロガーがある場合、ThreadAbortExceptionsが散らばります。この場合、これは予期される動作です。

直感的には、CSVファイルをブラウザーに送信しても例外は発生しません。

詳細はこちらをご覧ください Response.End()は有害と考えられますか?

6
user2023861

これは、DataTableを取得してCSVに変換するCSVアクションの結果です。ビューからこれを返すことができ、ファイルをダウンロードするようユーザーに促します。これを簡単にリスト互換フォームに変換するか、リストを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

ファイルに書き込む方法(Googleでの簡単な検索)... 最初の検索結果

ユーザーがページにアクセスするたびにファイルを作成する限り、...各アクセスはそれ自身のために動作します。あなたのビジネスケースが行動を決定します。

ケース1-同じファイルですが、変更されません(このタイプのケースでは、複数の定義方法があります)

  • 必要なときにファイルを作成し、生成が不要な場合にのみファイルにアクセスするロジックがあります。

ケース2-各ユーザーが独自のファイルを生成する必要がある

  • 各ユーザーを識別する方法を決定し、各ユーザー用のファイルを作成し、表示されるはずのファイルにアクセスします。これはケース1と簡単にマージできます。 。

ケース3-同じファイルですが、アクセスごとに生成が必要

  • 使用例2では、​​これにより毎回生成が発生しますが、アクセスするとクリーンアップされます。
1
Jamie Altizer

http://www.codeproject.com/KB/cs/CsvReaderAndWriter.aspx でcsvreader/writerライブラリを確認してください

0
dankyy1