1

ツリービューを含むASP.NET(3.5)Webサイトで作業しています。ノードの値は、PDFファイルの(サーバー上の)ファイルパスに設定されます。ユーザーがツリーノードをクリックすると、サーバー側のコードはノード値(ファイルパス)を取得し、FileInfoオブジェクトを作成し、(すべてのヘッダーContent-type、Cache-Controlなどを正しく設定した後)Response.TransmitFile( xxxxpath)ユーザーのブラウザに送信します。

これは、主要なブラウザ、主要なデバイス(PC、Mac、iOSデバイス)で正常に機能します。ファイルが正しくダウンロードされ、ユーザーのマシンで開きます。ただし、特定のデバイスおよび特定のブラウザーでは、PDFファイルが開きません。Androidデバイスでは、FirefoxがPDFを正しくダウンロードして開くように見えますが、標準のAndroidブラウザはそうではありません。Kindle Fireでは、Silkブラウザーがファイルを正常にダウンロードしたように見えますが、ファイルを開こうとすると、「PDFトレーラーが見つかりません」というエラーが表示されます。または、PDFがDRMで保護されていると表示されます(これはいいえ)。Fireで別のブラウザ(ある場合)を試したことはありません。

静的HTMLマークアップでアンカーリンクを使用して実験しましたが、この方法でアクセスすると、問題のあるブラウザーがPDFを正しくダウンロードして表示するように見えます。コードを介してASP.NETがブラウザに応答を送信する方法に問題(不整合?)があるようです。Response.Flush、Response.WriteFile、Response.BinaryWrite、Response.Close、Response.Endなどを使用しましたが、すべて同じ結果が得られます。ほとんどのブラウザーはファイルを処理しますが、一部のブラウザーはPDFを処理できません。

では、ASP.NETがResponseオブジェクトを構築する方法(特にPDFを返送する場合)に、一部のブラウザーが気に入らない問題がありますか?TIA。

4

1 に答える 1

1

簡単に言えば、あなたの質問に対する答えは「いいえ」です。コードを正しく実行しているかどうか疑問がある場合は、コードを投稿することをお勧めします。それ以外の場合: 「いいえ」。:)

あなたが言及したブラウザーは、応答ストリームへの書き込みのように単純で確立されたものよりもはるかに疑わしいと思います。

参考までに、iHttpHandler を使用して実証済みの真の方法を次に示します。

    public void ProcessRequest(System.Web.HttpContext context)
    {
        string sFilePath = context.Server.MapPath(String.Concat("~/App_LocalResources", context.Request.QueryString["path"]));
        try
        {
            context.Response.Clear();
            context.Response.ContentType = "application/octet-stream";

            int iReadLength = 16384;
            int iLastReadLength = iReadLength;
            byte[] buffer = new byte[iReadLength];
            if (System.IO.File.Exists(sFilePath))
            {
                System.IO.FileInfo fInfo = new System.IO.FileInfo(sFilePath);
                context.Response.AddHeader("Content-Length", fInfo.Length.ToString());
                context.Response.AddHeader("Content-Disposition", String.Format("attachment; filename=\"{0}\"", fInfo.Name));
                using (System.IO.FileStream input = new System.IO.FileStream(sFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    try
                    {
                        while (iLastReadLength > 0 && context.Response.IsClientConnected)
                        {
                            iLastReadLength = input.Read(buffer, 0, iLastReadLength);

                            if (iLastReadLength > 0)
                            {
                                context.Response.OutputStream.Write(buffer, 0, iLastReadLength);
                                context.Response.OutputStream.Flush();
                            }
                        }
                        context.Response.Flush();
                    }
                    catch
                    {
                    }
                    finally
                    {
                        input.Close();
                    }
                }
            }
        }
        catch
        {
        }
        finally
        {
        }
    }

ファイルを別の場所からプルしていることを示したので、それをメモリストリームに書き込む方法を次に示します。リモート サーバー (またはファイル ストリーム、Sql バイナリ リーダーなど) から応答ストリームを取得し、MemoryStream の位置をリセットしてから、上記の機能を使用して応答ストリームにクライアントに書き込みます。

int iReadLength = 16384;
long lLastReadLength = iReadLength;
long lDataIndex = 0;
byte[] buffer = new byte[iReadLength];
using (System.IO.MemoryStream msTemp = new System.IO.MemoryStream())
{
    while (lLastReadLength > 0)
    {
        lLastReadLength = reader.GetBytes(0, lDataIndex, buffer, 0, iReadLength);
        lDataIndex += lLastReadLength;

        if (lLastReadLength > 0)
        {
            msTemp.Write(buffer, 0, Convert.ToInt32(lLastReadLength));
            msTemp.Flush();
        }
    }

    // Reset Memory Position
    msTemp.Position = 0;

    // Now write to the Response Stream here
}
于 2012-10-01T02:03:37.137 に答える