23

Flush()StreamWriterオブジェクトを呼び出すと、基になるストリームに書き込むという印象を受けましたが、私のコードではそうではないようです。

私のファイルに書き込む代わりに、何も書き込まないだけです。私が間違っているアイデアはありますか?

    public FileResult DownloadEntries(int id)
    {
        Competition competition = dataService.GetCompetition(id);
        IQueryable<CompetitionEntry> entries = dataService.GetAllCompetitionEntries().Where(e => e.CompetitionId == competition.CompetitionId);

        MemoryStream stream = new MemoryStream();
        StreamWriter csvWriter = new StreamWriter(stream, Encoding.UTF8);

        csvWriter.WriteLine("First name,Second name,E-mail address,Preferred contact number,UserId\r\n");

        foreach (CompetitionEntry entry in entries)
        {
            csvWriter.WriteLine(String.Format("{0},{1},{2},{3},{4}",
                entry.User.FirstName,
                entry.User.LastName,
                entry.User.Email,
                entry.User.PreferredContactNumber,
                entry.User.Id));
        }

        csvWriter.Flush();

        return File(stream, "text/plain", "CompetitionEntries.csv");
    }
4

3 に答える 3

29

設定する必要があると思いますStream.Position = 0。書き込むと、位置をストリームの最後に進めます。あなたがそれを渡すとFile()、その位置から始まります - 終わり。

私は以下がうまくいくと思います(これをコンパイルしようとしませんでした):

stream.Position = 0;
return File(stream, "text/plain", "CompetitionEntries.csv");

この方法では、新しいオブジェクトを作成したり、基になる配列をコピーしたりしません。

于 2012-06-21T22:14:44.920 に答える
9

あなたの MemoryStream は最後に配置されています。より良いコードは、 MemoryStream(Byte[], Int32, Int32, Boolean)コンストラクターを使用して、同じバッファーに新しい R/o メモリ ストリームを作成することです。

トリムされたバッファでの最も単純な r/w:

 return File(new MemoryStream(stream.ToArray());

内部バッファをコピーせずに R/o:

 return File(new MemoryStream(stream.GetBuffer(), 0, (int)stream.Length, false);

注: File(Stream) を介して返すストリームを破棄しないように注意してください。そうしないと、何らかの「ObjectDisposedException」が発生します。つまり、元のストリームの位置を 0 に設定し、StreamWriter を使用してラップすると、破棄されたストリームが返されます。

于 2012-06-21T22:13:59.673 に答える
3

これで遊んで、私は次のプロトタイプを動作させることができました:

using System.Web.Mvc;
using NUnit.Framework;

namespace StackOverflowSandbox
{
[TestFixture]
public class FileStreamResultTest
{
    public FileStreamResult DownloadEntries(int id)
    {
        // fake data
        var entries = new[] {new CompetitionEntry { User = new Competitor { FirstName = "Joe", LastName = "Smith", Email = "jsmith@example.com", Id=id.ToString(), PreferredContactNumber = "555-1212"}}};

        using (var stream = new MemoryStream())
        {
            using (var csvWriter = new StreamWriter(stream, Encoding.UTF8))
            {
                csvWriter.WriteLine("First name,Second name,E-mail address,Preferred contact number,UserId\r\n");

                foreach (CompetitionEntry entry in entries)
                {
                    csvWriter.WriteLine(String.Format("{0},{1},{2},{3},{4}",
                                                      entry.User.FirstName,
                                                      entry.User.LastName,
                                                      entry.User.Email,
                                                      entry.User.PreferredContactNumber,
                                                      entry.User.Id));
                }

                csvWriter.Flush();
            }

            return new FileStreamResult(new MemoryStream(stream.ToArray()), "text/plain");
        }
    }

    [Test]
    public void CanRenderTest()
    {
        var fileStreamResult = DownloadEntries(1);
        string results;
        using (var stream = new StreamReader(fileStreamResult.FileStream))
        {
            results = stream.ReadToEnd();
        }
        Assert.IsNotEmpty(results);
    }
}

public class CompetitionEntry
{
    public Competitor User { get; set; }
}

public class Competitor
{
    public string FirstName;
    public string LastName;
    public string Email;
    public string PreferredContactNumber;
    public string Id;
}
}
于 2012-06-21T22:27:31.240 に答える