web-dev-qa-db-ja.com

Web API ControllerはMemoryStreamをStreamContentに変換します

セキュリティで保護されたサーバーに保存された画像の大規模なコレクションがあり、その一部は世界に面したポータルに表示する必要があります。ポータルのサーバーは、DMZ内にあります。これにより、リクエストは許可されますが、直接リクエストは保護されたドメインに移動できません。イメージはSOLRを使用してカタログされ、内部(apache?)サーバーからダウンロードできます) _http://intenalname/folderA/folderAB/file.jpg_

PhotoController内で、WebClientのインスタンスを作成し、URLを指定してMemoryStreamを取得できます。このメモリストリームを使用してresponse.contentを設定しようとすると、(フィドラーごとに)空の応答が返されます。メモリストリームを使用してローカルファイルに書き込み、ファイルを(FileStreamとFileInfoを使用して)読み取ると、「期待どおりに」動作します。

ファイルシステムを経由せずにMemoryStreamからStreamContentにアクセスできるはずです(そうではありません)。しかし、どのように? StreamContent(stream)のデフォルトコンストラクターは、コンパイラエラーなしでメモリストリームインスタンスを受け入れますが、それは単に「機能しません」。

_HttpResponseMessage response = Request.CreateResponse();

using (WebClient webClient = new WebClient())
{
    string url = string.Format(PHOTO_GET, filePath);
    using (MemoryStream memoryStream = new MemoryStream(webClient.DownloadData(url)))
    {
        // If these lines are unremarked the stream moves 'through' the file system and works (?!)
        //memoryStream.Position = 0;
        //string tempName = @"c:\test\" + Guid.NewGuid().ToString() + ".jpg";
        //var fs = new FileStream(tempName, FileMode.OpenOrCreate);
        //stream.CopyTo(fs);
        //fs.Close();
        //FileInfo fi = new FileInfo(tempName);

        response.Headers.AcceptRanges.Add("bytes");
        response.StatusCode = HttpStatusCode.OK;
        //response.Content =  new StreamContent(fi.ReadStream());
        response.Content = new StreamContent(memoryStream);
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("render");
        response.Content.Headers.ContentDisposition.FileName = fileName;
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");//("application/octet-stream");
        response.Content.Headers.ContentLength = memoryStream.Length;

    }

}
return response;
_

Fiddlerを介してテストすると、次の結果が得られます。

[Fiddler] ReadResponse()failed:サーバーはこのリクエストに対して完全なレスポンスを返しませんでした。サーバーは0バイトを返しました。

(FileStream Fiddlerを使用するときに画像が表示されます。)

16
Cos Callis

コードでは、メモリストリームはコンテンツを応答に渡す前に破棄されます。返される応答は破棄されたメモリストリームを使用するため、何も返す必要がないため、フィドラーの0バイトになります。

HttpResponseMessage response = Request.CreateResponse();

using (WebClient webClient = new WebClient())
{
    string url = string.Format(PHOTO_GET, filePath);
    var memoryStream = new MemoryStream(webClient.DownloadData(url));

    response.Headers.AcceptRanges.Add("bytes");
    response.StatusCode = HttpStatusCode.OK;
    response.Content = new StreamContent(memoryStream);
    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("render");
    response.Content.Headers.ContentDisposition.FileName = fileName;
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
    response.Content.Headers.ContentLength = memoryStream.Length;            
}
return response;
26
Nkosi