MVC3とIISURLRewrite 2を使用してGridFSから画像とそのサイズ変更されたバージョンを提供するシステムを作成しようとしています。テスト後、ファイルシステムから直接画像を提供する方が、GridFSファイルストリームを使用して提供するよりも10倍高速であることがわかりました。次に、元のファイルをGridFSに保持し、Url Rewrite 2ハンドラーとAsp.Netハンドラーの組み合わせを使用して、サーバーのローカルファイルシステムに元のファイルとサイズ変更されたバージョンのコピーを作成することにしました。
元のバージョンとサイズ変更されたバージョンを提供するために使用する書き換えルールは次のとおりです。
<rule name="Serve Resized Image" stopProcessing="true">
<match url="images/([a-z]+)/[a-f0-9]+/[a-f0-9]+/[a-f0-9]+/([a-f0-9]+)-([a-f0-9]+)-([a-f0-9]+)-([0-9]+)\.(.+)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="/Handlers/ImageResizer.ashx?Uri={REQUEST_URI}&Type={R:1}&Id={R:2}&Width={R:3}&Height={R:4}&ResizeType={R:5}&Extension={R:6}" appendQueryString="false" logRewrittenUrl="true" />
</rule>
<rule name="Serve Original Image" stopProcessing="true">
<match url="images/([a-z]+)/[a-f0-9]+/[a-f0-9]+/[a-f0-9]+/([a-f0-9]+)\.(.+)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="/Handlers/Images.ashx?Uri={REQUEST_URI}&Type={R:1}&Id={R:2}&Extension={R:3}" appendQueryString="false" logRewrittenUrl="true" />
</rule>
ご覧のとおり、書き換えエンジンはファイルがファイルシステムに存在するかどうかをチェックし、存在しない場合はチェックします。URLを書き換えて、リクエストをハンドラーに送信します。ハンドラーはストリームを提供し、ファイルをファイルシステムに書き込みます。次のリクエストでは、ファイルはファイルシステムから直接提供されます。同じフォルダーに何千もの画像が含まれるのを避けるために、24文字のID(文字列としてのMongoDBオブジェクトID)を分割して、ファイルをフォルダーに分けました。
オリジナル画像リクエストのサンプルは次のとおりです。
http://localhost/images/test/50115c53/1f37e409/4c7ab27d/50115c531f37e4094c7ab27d.jpg
これとサイズ変更されたバージョンは問題なく動作します。
このURLは長すぎて重複しているため、再度書き換えエンジンを使用してURLを短縮し、フォルダ名を自動的に生成することにしました。これが私が一番上に置いたルールです:
<rule name="Short Path for Images">
<match url="images/([a-z]+)/([a-f0-9]{8})([a-f0-9]{8})([a-f0-9]{8})(.+)" />
<action type="Rewrite" url="images/{R:1}/{R:2}/{R:3}/{R:4}/{R:2}{R:3}{R:4}{R:5}" appendQueryString="false" logRewrittenUrl="true"></action>
</rule>
このルールを使用して、たとえば次のURLで画像をリクエストすると、次のようになります。
http://localhost/images/test/50115c531f37e4094c7ab27d.jpg
画像がすでにファイルシステム上にある場合にのみ画像を提供します。そうでない場合、次のエラーが発生します。
HTTPエラー500.50-URL書き換えモジュールエラー。内部サーバーエラーが発生したため、ページを表示できません。
リクエストのIISログファイルエントリを確認しました。以下を除いて詳細は表示されません。
2012-08-02 14:44:51 127.0.0.1 GET /images/test/50115c531f37e4094c7ab27d.jpg - 80 - 127.0.0.1 Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.1+(KHTML,+like+Gecko)+Chrome/21.0.1180.60+Safari/537.1 500 50 161 37
一方、成功したリクエストは、書き換えられたURLを次のようにログに記録します。
GET /Handlers/ImageResizer.ashx Uri=/images/test/50115c53/1f37e409/4c7ab27d/50115c531f37e4094c7ab27d-1f4-1f4-2.jpg&Type=test&Id=50115c531f37e4094c7ab27d&Width=1f4&Height=1f4&ResizeType=2&Extension=jpg
ElmahとEventLogも何も表示しません。コントローラメソッドの先頭にファイルシステムロガーを追加しましたが、これらの特定の問題のあるリクエストはログに記録されません。
誰かがそれを機能させるための回避策を提案できますか?
編集:失敗したリクエストのトレースに関するRuslanYの提案の後、私はエラーを特定することができました:
ModuleName: RewriteModule
Notification: 1
HttpStatus: 500
HttpReason: URL Rewrite Module Error.
HttpSubStatus: 50
ErrorCode: 2147942561
ConfigExceptionInfo:
Notification: BEGIN_REQUEST
ErrorCode: The specified path is invalid. (0x800700a1)
トレース結果全体はここで確認できます(IEのみ)
残念ながら、ファイルがファイルシステムに存在する場合、2番目のルール(したがって短縮ルール)が機能しているため、これでも解決策にたどり着きません。