3

FILESTREAM をサポートする SQL データベースをセットアップし、WebAPI を介して SqlFileStream を使用してデータベースから取得したファイルをブラウザーにストリーミングしようとしています。

何らかの理由で機能しませんが、適切なエラー メッセージが表示されません。ブラウザーは接続を中止するだけで、Fiddler も有用なものを何も表示せず、VS でエラーがスローされないようです。

public HttpResponseMessage Get(Guid id)
{
    if(id == null || id == Guid.Empty)
        return Request.CreateResponse(HttpStatusCode.BadRequest);

    try
    {
        FileStreamContext fsc = null;
        Document document = null;
        using(var transaction = new TransactionScope())
        using (var db = new MyEntities())
        {
            try
            {
                fsc = db.Database.SqlQuery<FileStreamContext>("SELECT [File].PathName() AS InternalPath, GET_FILESTREAM_TRANSACTION_CONTEXT() AS TransactionContext FROM Document WHERE id={0}", id).First();
            }
            catch (Exception e)
            {
                Debug.Print(e.ToString());
            }

            document = db.Documents.Where(doc => doc.ID == id).Single();

            var fileStream = new SqlFileStream(fsc.InternalPath, fsc.TransactionContext, FileAccess.Read);

            HttpResponseMessage response = new HttpResponseMessage();
            response.Content = new StreamContent(fileStream);
            //response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            //response.Content.Headers.ContentDisposition.FileName = document.FileName;
            response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(document.ContentType);
            return response;
        }
    }
    catch (Exception e)
    {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
}

TransactionScope が早期に閉じられていることに問題があるのではないかと思いますか? エラーメッセージが表示されない理由はわかりません。

WebApiを介してSqlFileStreamをストリーミングする適切な方法は何ですか?

4

1 に答える 1

0

コンテンツを として設定する代わりに、コントローラーで をStreamContent読み取り、それを配列にfileStream入れてから、を使用してコンテンツを設定しようとしましたか?byteByteArrayContent

var fileStream = new SqlFileStream(fsc.InternalPath, fsc.TransactionContext, FileAccess.Read);
byte[] fileContent = fileStream.ReadFully(); // you will need to implement ReadFully
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new ByteArrayContent(fileContent);

ReadFully実装については、私が使用した Jon Skeet メソッドへのリンクを次に示します。

そして、接続があまりにも早く閉じられていることについては、あなたが正しいと思います。あなたはDbContext/をブロックにObjectContextうまくラップしていますusingが、それが問題だと思います。そのコンテキストは、コントローラーが を返した後に破棄されますが、応答はストリームにしかアクセスできません。ブラウザーまたはクライアントに戻す前にHttpResponseMessage、ストリームを読み取って に変換する必要があります。フレームワークはストリームにアクセスしてその内容を読み取ることができるため、byte[]これは通常 a などを使用しているときに自動的に行われます。MemoryStreamただし、この場合、ストリームを読み取る前に SQL 接続を破棄しています。

DbContext別の解決策は、アクション メソッドでそれを新しくする代わりに、依存性注入を使用することです。HTTP 要求の最後にコンテキストを自動的に破棄するように IoC コンテナーを設定した場合、フレームワークが を に変換してネットワーク経由でプッシュするときに、コンテキストは引き続き使用可能 (未処理) である必要がありStreamContentますbyte[]

于 2013-08-09T17:22:04.973 に答える