Xiaoyu Zhang
Xiaoyu Zhang

Reputation: 11

c# web api return with whole file instead of byte array

for my current web api, i return a file as byte[] and it works via the code follows.

[Route("GetReferenceFile")]
    [HttpPost]
    public HttpResponseMessage GetReferenceFile([FromBody]ReferenceFileMonitorRetrievingRequest request)
    {
        try
        {
            var fileName = request.fileName;
            //get file path
            var filePathWoFileName = _manager.GetReferenceFileForReferenceFileMonitor(request.fileName, request.fileFolderPathWithFileName);
            //convert file into bytes array
            var dataBytes = File.ReadAllBytes(filePathWoFileName + request.fileName);
            //add bytes to memory stream 
            var dataStream = new MemoryStream(dataBytes);
            //send out
            HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
            httpResponseMessage.Content = new StreamContent(dataStream);
            httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
            httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");

            return httpResponseMessage;
        }
        catch (IOException e)
        {
            logger.Error("Error Message: " + e.Message + " Stack Trace: " + e.StackTrace);
            return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
        }
        catch (Exception ex)
        {
            logger.Error("Error Message: " + ex.Message + " Stack Trace: " + ex.StackTrace);
            return Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
        }

may i ask that is there any other way to send the whole file over instead of read the file as byte[] and send over? because i was afraid that reading as byte[] may change the file a bit, for example: the space made by "Tab" may not remain the same.

Thank you in advance.


Edited:

i used System.Text.Encoding.UTF8.GetString(//byte array) to convert byte array to string and write to file. will this raise any concern of changing the original file content? Thank you.

public async Task<string> GetReferenceFile(ReferenceFileRequest referenceFileRequest)
    {
        ConfigurationManager.RefreshSection("appSettings");
        var URL = ConfigurationManager.AppSettings["GetReferenceFile"];
        byte[] refFile = new byte[0];
        try
        {
            Client.DefaultRequestHeaders.Accept.Clear();
            Client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = await Client.PostAsJsonAsync(URL, referenceFileRequest);

            refFile = await response.Content.ReadAsByteArrayAsync();
            return System.Text.Encoding.UTF8.GetString(refFile); //Convert to string
        }
        catch (Exception ex)
        {
            logData.LogError("Error Message: " + ex.Message + " Stack Trace: " + ex.StackTrace);
            return null;
        }
    }

Upvotes: 0

Views: 5107

Answers (1)

ProgrammingLlama
ProgrammingLlama

Reputation: 38767

To address your concerns: bytes are the lowest level that .NET can read a file at using the standard IO code. When you read bytes, you're reading the raw file data. It doesn't matter if it's an EXE, a Word document, or a text file. The problems you describe can happen when you start trying to try to convert between bytes and text using the wrong encoding. Since you're not doing anything like that here, you should have no problems.

You can make an optimization, however. At the moment you're reading the entire file into memory. You can instead pipe the file directly to the response.

Replace this code:

var dataBytes = File.ReadAllBytes(filePathWoFileName + request.fileName);
//add bytes to memory stream 
var dataStream = new MemoryStream(dataBytes);
//send out
HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(dataStream);

With this:

var dataStream = File.OpenRead(filePathWoFileName + request.fileName);
//send out
HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(dataStream);

Upvotes: 2

Related Questions