2

SharePoint 2003 ドキュメント ライブラリに格納されているファイルをブラウザにストリーミングしようとしています。基本的には、ファイルをストリームとして開き、ファイル ストリームを応答に「書き込み」、コンテンツ タイプとコンテンツ ディスポジション ヘッダーを指定するという考え方です。コンテンツの処理は、ファイル名、コンテンツ タイプを保持するために使用されます。これは、ファイルを表示するためにどのアプリを開けばよいかをブラウザに知らせるためです。

これは、開発環境と UAT 環境で問題なく機能します。ただし、本番環境では、常に期待どおりに動作するとは限りませんが、IE6/IE7 のみです。FF はあらゆる環境でうまく機能します。

本番環境では SSL が有効になっており、一般的に使用されていることに注意してください。(実稼働環境で SSL が使用されていない場合、ファイル ストリームは期待どおりに名前が付けられ、適切に表示されます。)

コード スニペットを次に示します。

System.IO.FileStream fs = new System.IO.FileStream(Server.MapPath(".") + "\\" + "test.doc", System.IO.FileMode.Open);
long byteNum = fs.Length;
byte[] pdfBytes = new byte[byteNum];
fs.Read(pdfBytes, 0, (int)byteNum);

Response.AppendHeader("Content-disposition", "filename=Testme.doc");
Response.CacheControl = "no-cache";
Response.ContentType = "application/msword; charset=utf-8";
Response.Expires = -1;
Response.OutputStream.Write(pdfBytes, 0, pdfBytes.Length);
Response.Flush();
Response.Close();
fs.Close();

前述したように、このコード スニペットは開発マシンと UAT 環境で正常に動作します。ダイアログ ボックスが開き、Testme.doc の保存、表示、またはキャンセルを求められます。ただし、本番環境では SSL を使用する場合のみ、IE 6 および IE7 は添付ファイルの名前を使用しません。代わりに、ストリームを送信しているページの名前 testheader.apx を使用すると、エラーがスローされます。

IE には、「暗号化されたページをディスクに保存しない」という高度な設定があります。

これが問題の一部であると思われます。サーバーはブラウザーにファイルをキャッシュしないように指示しますが、IE では「暗号化されたページをディスクに保存しない」が有効になっています。

はい、大きなファイルの場合、上記のコード スニペットがメモリを大きく圧迫し、この実装が問題になることは承知しています。したがって、実際の最終的な解決策は、ファイル全体を 1 バイト配列に開くのではなく、ファイルをストリームとして開き、ファイルを一口サイズのチャンク (たとえば、サイズが約 10K) でクライアントに送信します。

SSL経由でバイナリファイルを「ストリーミング」する同様の経験をした人はいますか? 提案や推奨事項はありますか?

4

2 に答える 2

4

それは本当に単純なことかもしれませんが、信じられないかもしれませんが、今日私がまったく同じものをコーディングしたかどうかはわかりません。問題は、コンテンツの処理がブラウザーに添付ファイルを通知しないため、保存できることだと思います。


Response.AddHeader("Content-Disposition", "attachment;filename=myfile.doc");

https://で機能することがわかっているので、以下にコードを含めたことに失敗しました。


private void ReadFile(string URL)
{
  try
  {
                string uristring = URL;
                WebRequest myReq = WebRequest.Create(uristring);
                NetworkCredential netCredential = new NetworkCredential(ConfigurationManager.AppSettings["Username"].ToString(), 
                                                                        ConfigurationManager.AppSettings["Password"].ToString(), 
                                                                        ConfigurationManager.AppSettings["Domain"].ToString());
                myReq.Credentials = netCredential;
                StringBuilder strSource = new StringBuilder("");

                //get the stream of data 
                string contentType = "";
                MemoryStream ms;
                // Send a request to download the pdf document and then get the response
                using (HttpWebResponse response = (HttpWebResponse)myReq.GetResponse())
                {
                    contentType = response.ContentType;
                    // Get the stream from the server
                    using (Stream stream = response.GetResponseStream())
                    {
                        // Use the ReadFully method from the link above:
                        byte[] data = ReadFully(stream, response.ContentLength);
                        // Return the memory stream.
                        ms = new MemoryStream(data);
                    }
                }

                Response.Clear();
                Response.ContentType = contentType;
                Response.AddHeader("Content-Disposition", "attachment;");

                // Write the memory stream containing the pdf file directly to the Response object that gets sent to the client
                ms.WriteTo(Response.OutputStream);
  }
  catch (Exception ex)
  {
    throw new Exception("Error in ReadFile", ex);
  }
}

于 2008-09-09T22:49:19.647 に答える
3

わかりました、問題を解決しました。ここでいくつかの要因が関係しています。

まず、Microsoft のこのサポート記事は有益でした: Internet Explorer は SSL Web サイトから Office ドキュメントを開くことができません

Internet Explorer が Office (またはプロセス外の ActiveX ドキュメント サーバー) でドキュメントを開くには、Internet Explorer がファイルをローカル キャッシュ ディレクトリに保存し、関連するアプリケーションに IPersistFile::Load を使用してファイルを読み込むように要求する必要があります。 . ファイルがディスクに保存されていない場合、この操作は失敗します。

Internet Explorer が SSL を介してセキュリティで保護された Web サイトと通信する場合、Internet Explorer はキャッシュなしの要求を強制します。1 つまたは複数のヘッダーが存在する場合、Internet Explorer はファイルをキャッシュしません。したがって、Office はファイルを開くことができません。

2 つ目は、ページ処理の初期段階で「no-cache」ヘッダーが書き込まれる原因でした。そのため、Response.ClearHeaders を追加する必要がありました。これにより、no-cache ヘッダーが消去され、ページの出力でキャッシュを許可する必要があります。

3 番目に適切な対策として、Response.End にも追加されました。これにより、リクエストの有効期間内に他の処理が設定したヘッダーをクリアし、no-cache ヘッダーを再追加しようとしなくなります。

第 4 に、IIS でコンテンツの有効期限が有効になっていることを発見しました。Web サイト レベルで有効のままにしましたが、この 1 つの aspx ページがファイルをダウンロードするためのゲートウェイとして機能するため、ダウンロード ページ レベルで無効にしました。

動作するコード スニペットを次に示します (重要ではないと思われるマイナーな変更が他にもいくつかあります)。

System.IO.FileStream fs = new System.IO.FileStream(Server.MapPath(".") + "\\" + "TestMe.doc", System.IO.FileMode.Open);
long byteNum = fs.Length;
byte[] fileBytes = new byte[byteNum];
fs.Read(fileBytes, 0, (int)byteNum);

Response.ClearContent();
Response.ClearHeaders();
Response.AppendHeader("Content-disposition", "attachment; filename=Testme.doc");
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.ContentType = "application/octet-stream";
Response.OutputStream.Write(fileBytes, 0, fileBytes.Length);
Response.Flush();
Response.Close();
fs.Close();
Response.End();

これも説明のためのものであることを覚えておいてください。実際の製品コードには例外処理が含まれており、ファイルを一度にチャンク (おそらく 10K) ずつ読み取る可能性があります。

Mauro さん、コードに欠けていた詳細を見つけてくれてありがとう。

于 2008-09-16T22:30:28.403 に答える