8

私のasp.net Webアプリケーションの1つで、ユーザーに提供されているpdfファイルの場所を隠す必要があります。

したがって、CMS システム上のその場所からバイナリ コンテンツを取得し、バイト配列を Web ユーザーにフラッシュするメソッドを作成しています。

残念ながら、ストリームをダウンロードするときにエラーが発生します。

質問 1: 何が間違っていますか? 質問 2: このアプローチを使用して大きなファイルをダウンロードできますか?

    private void StreamFile(IItem documentItem)
    {
        //CMS vendor specific API
        BinaryContent itemBinaryContent = documentItem.getBinaryContent();
        //Plain old .NET
        Stream fileStream = itemBinaryContent.getContentStream();
        var len = itemBinaryContent.getContentLength();
        SendStream(fileStream, len, itemBinaryContent.getContentType());
    }

    private void SendStream(Stream stream, int contentLen, string contentType)
    {
        Response.ClearContent();
        Response.ContentType = contentType;
        Response.AppendHeader("content-Disposition", string.Format("inline;filename=file.pdf"));
        Response.AppendHeader("content-length", contentLen.ToString());
        var bytes = new byte[contentLen];
        stream.Read(bytes, 0, contentLen);
        stream.Close();
        Response.BinaryWrite(bytes);
        Response.Flush();
    }
4

6 に答える 6

7

これが私が使用する方法です。これにより添付ファイルが返されるため、IE は [開く/保存] ダイアログを生成します。また、ファイルが 1M を超えないことも知っているので、これを行うためのよりクリーンな方法があると確信しています。

PDF でも同様の問題があり、バイナリ ストリームと ReadBytes を絶対に使用する必要があることに気付きました。文字列のあるものはすべてそれを台無しにしました。

Stream stream = GetStream(); // Assuming you have a method that does this.
BinaryReader reader = new BinaryReader(stream);

HttpResponse response = HttpContext.Current.Response;
response.ContentType = "application/pdf";
response.AddHeader("Content-Disposition", "attachment; filename=file.pdf");
response.ClearContent();
response.OutputStream.Write(reader.ReadBytes(1000000), 0, 1000000);

// End the response to prevent further work by the page processor.
response.End();
于 2009-08-19T21:06:20.917 に答える
7

他の回答は、応答を送信する前にファイルの内容をメモリにコピーします。データが既にメモリ内にある場合は、2 つのコピーが作成されるため、スケーラビリティにはあまり適していません。これは代わりにうまくいくかもしれません:

public void SendFile(Stream inputStream, long contentLength, string mimeType, string fileName)
{
    string clength = contentLength.ToString(CultureInfo.InvariantCulture);
    HttpResponse response = HttpContext.Current.Response;
    response.ContentType = mimeType;
    response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
    if (contentLength != -1) response.AddHeader("Content-Length", clength);
    response.ClearContent();
    inputStream.CopyTo(response.OutputStream);
    response.OutputStream.Flush();
    response.End();
}

Stream はバイトのコレクションであるため、BinaryReader を使用する必要はありません。また、入力ストリームがファイルの最後で終了している限り、Web ブラウザーに送信するストリームで CopyTo() メソッドを使用するだけです。データの中間コピーを作成することなく、すべてのコンテンツがターゲット ストリームに書き込まれます。

ストリームから特定のバイト数だけをコピーする必要がある場合は、いくつかの CopyTo() オーバーロードを追加する拡張メソッドを作成できます。

public static class Extensions
{
    public static void CopyTo(this Stream inStream, Stream outStream, long length)
    {
        CopyTo(inStream, outStream, length, 4096);
    }

    public static void CopyTo(this Stream inStream, Stream outStream, long length, int blockSize)
    {
        byte[] buffer = new byte[blockSize];
        long currentPosition = 0;

        while (true)
        {
            int read = inStream.Read(buffer, 0, blockSize);
            if (read == 0) break;
            long cPosition = currentPosition + read;
            if (cPosition > length) read = read - Convert.ToInt32(cPosition - length);
            outStream.Write(buffer, 0, read);
            currentPosition += read;
            if (currentPosition >= length) break;
        }
    }
}

その後、次のように使用できます。

inputStream.CopyTo(response.OutputStream, contentLength);

これはどの入力ストリームでも機能しますが、簡単な例としては、ファイル システムからファイルを読み取る場合があります。

string filename = @"C:\dirs.txt";
using (FileStream fs = File.Open(filename, FileMode.Open))
{
    SendFile(fs, fs.Length, "application/octet-stream", filename);
}

前述のように、MIME タイプがコンテンツに対して正しいことを確認してください。

于 2010-07-08T22:08:58.543 に答える
1

このスニペットは私のためにそれをしました:

                Response.Clear();
                Response.ClearContent();
                Response.ClearHeaders();
                Response.ContentType = mimeType;
                Response.AddHeader("Content-Disposition", "attachment");
                Response.WriteFile(filePath);
                Response.Flush();
于 2009-11-11T21:33:46.897 に答える
0

私は現在の2.0Webサイトで同様の作業を行っています。久しぶりですが、うまく動かせなかったのを覚えていません。

しかし、私があなたが持っているものとはいくつかの違いがあります。うまくいけば、これらはあなたが問題を解決するのに役立つでしょう。

  • ClearContent呼び出しの後、ClearHeaders();を呼び出します。
  • 長さを指定していません。
  • 私は性向についてインラインで指定していません
  • 私は誰もがそれをしないと言っていることを知っていますが、私はResponse.Flush();を持っています。続いてResponse.Close();

そして、もう1つ、contentType値をチェックして、PDF(( "Application / pdf")に対して正しいことを確認します。

于 2009-08-19T16:39:08.960 に答える