1

I have use a method and retrieve files stored from Database without any problem in my project build on ASP.NET MVC and Angular:

[HttpPost]
public ActionResult GetFile(int id)
{
    var file= service.GetFileById(id);
    if (file.Data != null)
    {
        return File(file.Data, file.MimeType, file.Name);
    }
    return new EmptyResult();
}

On the other hand, when I want to use the same approach in my Web Api Controller, there is not such a kind of File() method and I tried to use the following method after looking at 15-20 solution on stackoverflow:

[Route("api/Generate/{id}")]
[AcceptVerbs("GET", "POST")]
public HttpResponseMessage Generate(int id)
{
    var data = service.GetFileByName(id);
    var stream = new MemoryStream();

    var result = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new ByteArrayContent(stream.ToArray())
    };
    result.Content.Headers.ContentDisposition =
        new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
        {
            FileName = data.Name
        };
    result.Content.Headers.ContentType =
        new MediaTypeHeaderValue(data.MimeType);

    return result;
}

However, there is no extension of the downloaded files and I have not found a useful method in order o get file extension from mime type as shown below (this method gets file type from application/pdf, but cannot get if the mime type is application/octet-stream. So, any idea to fix this problem for Web Api???

R. Richards
  • 24,603
  • 10
  • 64
  • 64
Jack
  • 1
  • 21
  • 118
  • 236

3 Answers3

1

If storing file names with extensions in db is impossible, then you should calculate extension by mime type.

Here is an answer about vice-versa solution. You can use your own mapping table. But if there will be multiple extensions for specific mime type, then you should decide which to choose

aleha_84
  • 8,309
  • 2
  • 38
  • 46
0

You have to install Nuget package like MediaTypeMap or write a custom method which return .ext of file based on MimeType. refer this link for all mime details.

I added code for get file extension using MediaTypeMap Nuget.

 using (MemoryStream stream = new System.IO.MemoryStream())
            {
                var result = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new ByteArrayContent(stream.ToArray())
                };
                result.Content.Headers.ContentDisposition =
                    new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
                    {
                        FileName = data.Name + MimeTypeMap.GetExtension(data.MimeType)
                    };
                result.Content.Headers.ContentType = new MediaTypeHeaderValue(data.MimeType);
                var response = ResponseMessage(result);
                return response;
            }
Divyang Patel
  • 920
  • 1
  • 8
  • 15
0

As I understand it, you want to derive your file extension from the file information that you have on hand. I think that you have binary file contents, a file name without an extension, and a mime type (aka content type).

To derive the extension from the mime type you can use some kind of mapping dictionary as others have mentioned. Divyang Patel's answer shows how you can do this.

An additional option would be to heuristically derive an extension (or mime type) from the file contents. I generally wouldn't recommend this option because it is resource intensive, but I thought I'd mention it for completeness.

TrID is the only option that I personally know of to do this. I'm sure there are others. There's a CLI, a .NET GUI, and a Nuget library (unofficial I think).

Here's an example of the package usage:

string extension = TrIDEngine.GetExtensionByFileContent(@"C:\path\to\file.???");

As far as I can tell this library offers no public interface that accept anything other than a file system path. This is unfortunate because in some cases the file contents could be streamed from somewhere besides the file system.

For your use case, if you should choose to go this route, here's how it could work:

  1. Write the file contents to a temporary file system location (if you don't already have a file path that can be used to read the file).
  2. Use TrID to derive the extension.
  3. Send response to client including the derived file extension and the file's contents.
  4. Delete (or queue the deletion) of any temporary files that were written.

In any case, I would strive to store any derived file extensions for subsequent requests.

Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346