Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API Controller convert MemoryStream into StreamContent

I have a large collection of images stored on a secured server some of which need to be displayed on a world facing portal. The portal's server is inside a DMZ which allows requests in but prevents direct requests from moving through to secured domain. The images are cataloged using SOLR and can be downloaded via an internal (apache?) server from http://intenalname/folderA/folderAB/file.jpg

Inside my PhotoController I can create an instance of the WebClient, give it the url and get a MemoryStream. If I attempt to use this memory stream to populate the response.content I get an empty response (per fiddler). If I use the memory stream to write to a local file, then read the file (using a FileStream and FileInfo) it works "as expected".

I should be able to get from a MemoryStream to StreamContent without going through the file system (shouldn't I) ?? but How? The default constructor for StreamContent(stream) accepts the memory stream instance without a compiler error...but it just 'doesn't work'.

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;

When testing via Fiddler I get:

[Fiddler] ReadResponse() failed: The server did not return a complete response for this request. Server returned 0 bytes.

(when going through FileStream Fiddler shows me the image.)

like image 447
Cos Callis Avatar asked May 04 '16 18:05

Cos Callis


1 Answers

In your code the memory stream is being disposed before it can pass it's content to the response. The returned response will be using a disposed memory stream so there is notheing to return, hence the 0 bytes in fiddler.

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;
like image 199
Nkosi Avatar answered Sep 28 '22 03:09

Nkosi