SmithsonG
SmithsonG

Reputation: 59

How To Read (GET) from File if Extension is Unknown - .NET Core 6 API

I have a controller, which I will include the methods for at the end. I allow users to upload either .DOC, .DOCX or .PDF files via my POST method.

I then have a GET method which I can currently return a file from, but it is hardcoded to .PDF. I want to know how I would enable my GET method read from any of the file types above? Or how would I get the file extension of a file, before I have read it into a stream?

If you have any feedback on my approach to either method, feedback is welcome!

    [HttpGet("Download/{requestId}/{lineNumber}")]
    public IActionResult Download([FromRoute] long requestId, [FromRoute] int lineNumber)
    {
        string fileName = requestId.ToString() + lineNumber.ToString();
        string fileDownloadName = fileName + DateTime.Now.ToString("ddMMyyyy");
        try
        {
            FileStream stream = new(GetFilePath() + fileName + ".pdf", FileMode.Open);
            return File(stream, "application/pdf", fileDownloadName + ".pdf");
        }

        catch (Exception ex)
        {
            return BadRequest(ex.Message);
        }
    }

    [HttpPost("Upload/{requestId}/{lineNumber}")]
    public async Task<IActionResult> OnPostUploadAsync(IFormFile formFile, [FromRoute] long requestId, [FromRoute] int lineNumber)
    {
        try
        {
            if (formFile.Length > 0)
            {
                string filename = formFile.FileName;
                string filepath = GetFilePath();
                string docId = requestId.ToString() + lineNumber.ToString();

                var supportedTypes = new[] { "doc", "docx", "pdf" };
                var fileExt = System.IO.Path.GetExtension(formFile.FileName).Substring(1);

                string concessionDocumentPath = filepath + "\\" + docId + "." + fileExt;

                if (!supportedTypes.Contains(fileExt))
                {
                    string ErrorMessage = "File Extension Is Invalid - Only Upload WORD/PDF File";
                    return BadRequest(ErrorMessage);
                }

                if (!System.IO.Directory.Exists(filepath))
                {
                    System.IO.Directory.CreateDirectory(filepath);
                }

                if (System.IO.File.Exists(concessionDocumentPath))
                {
                    System.IO.File.Delete(concessionDocumentPath);
                }
                using (FileStream stream = System.IO.File.Create(concessionDocumentPath))
                {
                    await formFile.CopyToAsync(stream);
                }
            }
        }
        catch (Exception ex)
        {
            return BadRequest(ex.Message);
        }

        return Ok(formFile.FileName.ToString() + " was uploaded successfully");
    }

    [NonAction]
    private string GetFilePath()
    {
        return this._environment.WebRootPath + "\\Uploads\\ConcessionDocuments\\";
    }

Upvotes: 0

Views: 1066

Answers (2)

SmithsonG
SmithsonG

Reputation: 59

With thanks to @WisdomSeeker for his help, I was able to get a solution in place. Instead of using GetFiles, I used EnumerateFiles

I'm doubtful it's the most effective, or best way to do this, but it works for what I need.

    [HttpGet("Download/{requestId}/{lineNumber}")]
    public IActionResult Download([FromRoute] long requestId, [FromRoute] int lineNumber)
    {
        string fileName = requestId.ToString() + lineNumber.ToString();
        string fileDownloadName = fileName + DateTime.Now.ToString("ddMMyyyy");
        string extension = null!;
        string mimeType = null!;
        string filePath;

        try
        {
            IEnumerable<string> directory = Directory.EnumerateFiles(GetFilePath(), fileName + "*");

            if (directory.Any())
            {
                filePath = directory.FirstOrDefault()!;

                if (filePath.EndsWith(".pdf"))
                {
                    extension = ".pdf";
                    mimeType = "application/pdf";
                }
                else if (filePath.EndsWith(".doc"))
                {
                    extension = ".doc";
                    mimeType = "application/msword";
                }
                else if (filePath.EndsWith(".docx"))
                {
                    extension = ".docx";
                    mimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                }

                FileStream stream = new(GetFilePath() + fileName + extension, FileMode.Open);

                return File(stream, mimeType, fileDownloadName + extension);
            }
            else
            {
                return BadRequest();
            }

        }
        catch (Exception ex)
        {
            return BadRequest(ex.Message);
        }
    }

Upvotes: 0

WisdomSeeker
WisdomSeeker

Reputation: 934

One way I could think of for getting the file extension is

DirectoryInfo di = new DirectoryInfo(GetFilePath());
FileInfo fileInfo = di.GetFiles().FirstOrDefault();

string fileExtension = System.IO.Path.GetExtension(fileInfo.FullName);

and you could use this extension in the hardcoded part.

Here I assumed you have only one file in the directory. Now if you have multiple files in the directory, try to identify the file using searchPattern overload of GetFiles.

Hope this helps.

Upvotes: 2

Related Questions