Source

main / Source / WebClient / Web.BizLogic / Services / UploadService.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataUp.Web.DataLayer;
using DataUp.Web.Common;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Spreadsheet;

namespace DataUp.Web.BizLogic
{
    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class UploadService : IUploadService
    {
        private IBlobDataRepository blobDataRepository;
        private IDocumentStoreRepository documentStoreRepository;

        public UploadService(IDocumentStoreRepository documentStoreRepository, IBlobDataRepository blobDataRepository)
        {
            this.documentStoreRepository = documentStoreRepository;
            this.blobDataRepository = blobDataRepository;
        }

        public IDictionary<int, string> CheckIfExists(string[] fileNames, int userId)
        {
            IDictionary<int, string> existingList = new Dictionary<int, string>();

            var documents = this.documentStoreRepository.GetItems(
                document => fileNames.Contains(document.Filename) && document.UserId == userId 
                , document => document.Id 
                , false);

            if (documents != null && documents.Count() > 0)
            {
                foreach (var item in documents)
                {
                    existingList.Add(item.Id, item.Filename);
                }
            }

            return existingList;
        }

        public OperationStatus PublishFile(UploadDetails fileDetails)
        {
            OperationStatus status;
            try
            {
                if (Publish(fileDetails))
                {
                    this.documentStoreRepository.SaveChanges();

                    status = OperationStatus.CreateSuccessStatus();
                }
                else
                {
                    status = OperationStatus.CreateFailureStatus("Could not upload file");
                }
            }
            catch (Exception ex)
            {
                status = OperationStatus.CreateFailureStatus(ex);
            }

            return status;
        }

        private bool Publish(UploadDetails fileDetails)
        {
            bool status = false;
            bool isUpdate = true;
            DocumentStore document = null;

            document = this.documentStoreRepository.GetItem(
                item => item.UserId == fileDetails.CreatedById && string.Compare(item.Filename, fileDetails.FileName, StringComparison.OrdinalIgnoreCase) == 0);

            if (document == null)
            {
                isUpdate = false;

                document = new DocumentStore();
                document.Filename = fileDetails.FileName;
                document.Title = Path.GetFileNameWithoutExtension(fileDetails.FileName);
                document.UserId = fileDetails.CreatedById;
                document.UploadedDate = fileDetails.CreatedDateTime;
            }

            document.Status = DocumentStatus.Uploaded.ToString();
            document.Size = fileDetails.Data.Size;
            if (Path.GetExtension(fileDetails.FileName) == ".csv")
            {
                fileDetails.Data.DataStream = CreateExcelFromCsv(fileDetails.Data.DataStream, Path.GetFileNameWithoutExtension(fileDetails.FileName));
            }
            if (UploadFile(fileDetails, document))
            {
                if (!isUpdate)
                {
                    this.documentStoreRepository.Add(document);
                }
                else
                {
                    this.documentStoreRepository.Update(document);
                }

                if (fileDetails.Data.DataStream != null)
                {
                    using(Stream filestream = new MemoryStream())
                    {
                        fileDetails.Data.DataStream.CopyToStream(filestream);

                        using (SpreadsheetDocument excelDocument = SpreadsheetDocument.Open(filestream, true))
                        {
                            MetadataDetailList metadataList = excelDocument.GetMetadataDetails();
                            document.UpdateMetadata(metadataList);

                            var citaionNode = metadataList.Metadata.Where(item => item.Name == Constants.CitationContent).FirstOrDefault();
                            if (citaionNode != null)
                            {
                                document.Citation = citaionNode.Value;
                            }

                            var identifierNode = metadataList.Metadata.Where(item => item.Name == Constants.IdentifierKeyName).FirstOrDefault();
                            if (identifierNode != null)
                            {
                                document.Identifier = identifierNode.Value;
                            }
                        }
                    }
                }
                status = true;
            }

            return status;
        }

        public bool UploadFile(UploadDetails fileDetails, DocumentStore document)
        {
            bool uploadStatus = false;
            if (Constants.UploadToAzure)
            {
                fileDetails.Data.AzureId = Guid.NewGuid();
                if (UploadFile(fileDetails.Data))
                {
                    document.FileId = fileDetails.Data.AzureId.ToString();
                    document.FileData = null;
                    uploadStatus = true;
                }
            }
            else
            {
                document.FileId = string.Empty;

                // TODO: Get Byte Array from stream.
                // document.FileData = 

                uploadStatus = true;
            }

            document.Size = fileDetails.Data.DataStream.Length;
            document.MimeType = fileDetails.Data.MimeType;

            return uploadStatus;
        }

        private bool UploadFile(DataDetail details)
        {
            bool status = false;

            try
            {
                BlobDetails blobDetail = new BlobDetails();
                blobDetail.BlobID = details.AzureId.ToString();
                blobDetail.Data = details.DataStream;
                blobDetail.MimeType = details.MimeType;

                status = this.blobDataRepository.UploadFile(blobDetail);
            }
            catch (Exception)
            {
                status = false;
            }
            return status;
        }

        private Stream CreateExcelFromCsv(Stream fileStream, string sheetName)
        {
            string line = String.Empty;
            Stream excelDocument = null;
            SpreadsheetDocument spreadSheet = null; WorkbookPart workbookpart = null;
            Sheets sheets = null; WorksheetPart worksheetpart = null; Sheet sheet = null;
            List<OpenXmlElement> list = new List<OpenXmlElement>();
            fileStream.Position = 0;
            using (StreamReader reader = new StreamReader(fileStream))
            {
                line = reader.ReadLine();
                Row row = null;
                int rowIndex = 0;
                string[] arrList = null;
                List<OpenXmlElement> element = null;
                string nextCol = "A";
                if (!String.IsNullOrEmpty(line))
                {
                    do
                    {
                        rowIndex++;
                        nextCol = "A";
                        arrList = CsvHelper.ReadCsvValues(line);
                        element = new List<OpenXmlElement>();
                        foreach(var val in arrList)
                        {
                            element.Add(new Cell() { CellValue = new CellValue(val), DataType = CellValues.String, CellReference = nextCol + rowIndex });
                            nextCol = IncrementColRef(nextCol);
                        }
                        row = new Row(element);
                        list.Add(((OpenXmlElement)row));
                        row.RowIndex = (uint)rowIndex;
                        line = reader.ReadLine();
                        
                    }
                    while (line != null);
                }
            }

            try
            {
                excelDocument = new MemoryStream();
                spreadSheet = SpreadsheetDocument.Create(excelDocument, SpreadsheetDocumentType.Workbook, false);
                workbookpart = spreadSheet.AddWorkbookPart();
                workbookpart.Workbook = new Workbook();
                sheets = workbookpart.Workbook.AppendChild(new Sheets());
                worksheetpart = workbookpart.AddNewPart<WorksheetPart>();
                worksheetpart.Worksheet = new Worksheet(new SheetData(list));
                worksheetpart.Worksheet.Save();
                sheet = new Sheet()
                {
                    Id = workbookpart.GetIdOfPart(worksheetpart),
                    SheetId = (uint)(1),
                    Name = sheetName
                };
                sheets.AppendChild(sheet);
                workbookpart.Workbook.Save();
            }
            catch
            {
            }
            finally
            {
                sheet = null; sheets = null;
                workbookpart = null; worksheetpart = null;
                spreadSheet.Close();
            }
            return excelDocument;
        }

        /// <summary>
        /// Returns the next Column Name as it exists in Excel Sheet
        /// </summary>
        /// <param name="lastRef">The last ref.</param>
        /// <returns></returns>
        private string IncrementColRef(string lastRef)
        {
            char[] characters = lastRef.ToUpperInvariant().ToCharArray();
            int sum = 0;
            for (int i = 0; i < characters.Length; i++)
            {
                sum *= 26;
                sum += (characters[i] - 'A' + 1);
            }
            sum++;
            string columnName = String.Empty;
            int modulo;
            while (sum > 0)
            {
                modulo = (sum - 1) % 26;
                columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
                sum = (int)((sum - modulo) / 26);
            }
            return columnName;
        }
    }
}