Search code examples
c#asp.net-mvccsvfilestream

Looking for workaround due to FileStream.Create UnauthorizedAccessException


I am using FileStream.Create to upload a .csv file onto a server and then read it into a SQL database. Once it is read in, I just delete the file from the folder that it was written to. The goal is to just get the file into the database. This would run fine locally, but I cannot get write access on the new server so I get an UnauthorizedAccessException. I don't think that it is necessary to upload the file to the server to read it into the SQL table, but I am having trouble adjusting the code.

[HttpPost]
    public ActionResult UploadValidationTable(HttpPostedFileBase csvFile)
    {
        var inputFileDescription = new CsvFileDescription
        {
            SeparatorChar = ',',
            FirstLineHasColumnNames = true
        };
        var cc = new CsvContext();
        var filePath = uploadFile(csvFile.InputStream);
        var model = cc.Read<Credit>(filePath, inputFileDescription);

        try
        {
            var entity = new Entities();
            foreach (var item in model)
            {
                var tc = new TemporaryCsvUpload
                {
                    Id = item.Id,
                    Amount = item.Amount,
                    Date = item.Date,
                    Number = item.Number,
                    ReasonId = item.ReasonId,
                    Notes = item.Notes
                };
                entity.TemporaryCsvUploads.Add(tc);
            }
            entity.SaveChanges();

            System.IO.File.Delete(filePath);

Here is the uploadFile method:

        private string uploadFile(Stream serverFileStream)
    {
        const string directory = "~/Content/CSVUploads";

        var directoryExists = Directory.Exists(Server.MapPath(directory));

        if (!directoryExists)
        {
            Directory.CreateDirectory(Server.MapPath(directory));
        }

        var targetFolder = Server.MapPath(directory);
        var filename = Path.Combine(targetFolder, Guid.NewGuid() + ".csv");

        try
        {
            const int length = 256;
            var buffer = new byte[length];

            // write the required bytes
            using (var fs = new FileStream(filename, FileMode.Create))
            {
                int bytesRead;
                do
                {
                    bytesRead = serverFileStream.Read(buffer, 0, length);
                    fs.Write(buffer, 0, bytesRead);
                } while (bytesRead == length);
            }

            serverFileStream.Dispose();
            return filename;
        }
        catch (Exception)
        {
            return string.Empty;
        }
    }

To sum it up, I am uploading a .csv file to a temporary location, reading it into an object, reading it into a database, then deleting the .csv file out of the temporary location. I am using Linq2Csv to create the object. Can I do this without uploading the file to the server (because I can't get write access)?


Solution

  • According to http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library,

    you can read from a StreamReader

    Read<T>(StreamReader stream)
    Read<T>(StreamReader stream, CsvFileDescription fileDescription)
    

    You can probably use a streamreader (or a stringbuilder) to create your file instead of a csv - Write StringBuilder to Stream

    How to take a stringbuilder and convert it to a streamReader?

    and then send that to your CSVContext?