public string Upload(UploadStreamInfo request)
        {
            string result = null;
            var containerName = request.FolderName;

            var container = _cloudBlobClient.GetContainerReference(containerName);
            if (!container.Exists())
            {
                container.CreateIfNotExists(BlobContainerPublicAccessType.Blob);
            }

            var blob = container.GetBlockBlobReference(request.FileName);
            blob.Properties.ContentType = MimeTypeResolver.ResolveContentType(request.FileName);

            using (var memoryStream = new MemoryStream())
            {
                // upload to MemoryStream
                //memoryStream.SetLength(request.Length);
                request.FileByteStream.CopyTo(memoryStream);
                memoryStream.Position = 0;
                // fill blob
                blob.UploadFromStream(memoryStream);
            }

            result = blob.Uri.AbsolutePath.TrimStart('/');


            return result;
        }
        public string Upload(UploadStreamInfo request)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            string folderName;
            string fileName;
            string key;
            string storagePath = _storagePath;

            folderName = request.FolderName;
            fileName = request.FileName;
            key = string.Format(@"{0}/{1}", folderName, fileName);
            storagePath = string.Empty;


            if (!string.IsNullOrEmpty(folderName))
                CreateFolder(_storagePath, folderName);

            var storageFileName = string.Format(CultureInfo.CurrentCulture, @"{0}\{1}\{2}", _storagePath, folderName, fileName);

            UpdloadFile(request.FileByteStream, storageFileName);


            return key;

        }
		public override Task ExecutePostProcessingAsync()
		{
			// Upload the files to  blob storage and remove them from local disk
			foreach (var fileData in this.FileData)
			{
				var fileInfo = new FileInfo(fileData.LocalFileName);
				var fileName = fileData.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
				using (Stream stream = fileInfo.OpenRead())
				{
					var uploadStreamInfo = new UploadStreamInfo
					{
						FileByteStream = stream,
						FileName = fileName,
						Length = fileInfo.Length,
						FolderName = _folder
					};

					var blobKey = _blobProvider.Upload(uploadStreamInfo);

					BlobInfos.Add(new BlobInfo
					{
						ContentType = fileData.Headers.ContentType.MediaType,
						FileName = fileName,
						Size = fileInfo.Length,
						Key = blobKey
					});
					
				}
				File.Delete(fileData.LocalFileName);
			}

			return base.ExecutePostProcessingAsync();
		}
        public string Upload(UploadStreamInfo request)
        {
            if (request == null)
                throw new ArgumentNullException("request");

            var folderPath = GetAbsoluteStoragePathFromUrl(request.FolderName);

            if (!Directory.Exists(folderPath))
            {
                Directory.CreateDirectory(folderPath);
            }
            var storageFileName = Path.Combine(folderPath, request.FileName);
            UpdloadFile(request.FileByteStream, storageFileName);

            return Path.Combine(request.FolderName, request.FileName);
        }
        public string Upload(UploadStreamInfo request)
        {
            string result = null;
            var directoryPath = DefaultBlobContainerName;
            if (!string.IsNullOrEmpty(request.FolderName))
            {
                directoryPath = request.FolderName;
            }
            //Container name
            var containerName = GetContainerNameFromUrl(directoryPath);
            //directory path
            directoryPath = GetDirectoryPathFromUrl(directoryPath);

            var container = _cloudBlobClient.GetContainerReference(containerName);
            container.CreateIfNotExists(BlobContainerPublicAccessType.Blob);

            ICloudBlob blob = null;
            if (String.IsNullOrEmpty(directoryPath))
            {
                blob = container.GetBlockBlobReference(request.FileName);
            }
            else
            {
                directoryPath += directoryPath.EndsWith(_cloudBlobClient.DefaultDelimiter) ? request.FileName : _cloudBlobClient.DefaultDelimiter + request.FileName;
                blob = container.GetBlockBlobReference(directoryPath);
            }

            blob.Properties.ContentType = MimeTypeResolver.ResolveContentType(request.FileName);

            using (var memoryStream = new MemoryStream())
            {
                // upload to MemoryStream
                //memoryStream.SetLength(request.Length);
                request.FileByteStream.CopyTo(memoryStream);
                memoryStream.Position = 0;
                // fill blob
                blob.UploadFromStream(memoryStream);
            }
            result = blob.Uri.AbsolutePath.TrimStart('/');
            return result;
        }
        public IHttpActionResult UploadAssetFromUrl(string folder, [FromUri]string url)
        {
            using (var client = new WebClient())
            {
                var uploadInfo = new UploadStreamInfo
                {
                    FileByteStream = client.OpenRead(url),
                    FolderName = folder,
                    FileName = HttpUtility.UrlDecode(System.IO.Path.GetFileName(url))
                };

                var key = _blobProvider.Upload(uploadInfo);
                var retVal = new webModel.BlobInfo
                {

                    Name = uploadInfo.FileName,
                    RelativeUrl = key,
                    Url = _urlResolver.GetAbsoluteUrl(key)
                };
                return Ok(retVal);
            }

        }
		public virtual void DoExport(string catalogId, string[] exportedCategories, string[] exportedProducts, string pricelistId, string fulfilmentCenterId, CurrencyCodes currency, string languageCode, ExportNotification notification)
		{
			var memoryStream = new MemoryStream();
			var streamWriter = new StreamWriter(memoryStream);
			streamWriter.AutoFlush = true;
			var productPropertyInfos = typeof(CatalogProduct).GetProperties(BindingFlags.Instance | BindingFlags.Public);
			string catalogName = null;
			using (var csvWriter = new CsvWriter(streamWriter))
			{
				csvWriter.Configuration.Delimiter = ";";

				//Notification
				notification.Description = "loading products...";
				_notifier.Upsert(notification);

				try
				{
					//Load all products to export
					var products = LoadProducts(catalogId, exportedCategories, exportedProducts);

					//Notification
					notification.Description = "loading prices...";
					_notifier.Upsert(notification);
					var allProductIds = products.Select(x=>x.Id).ToArray();
					//Load prices for products
					var priceEvalContext = new  PriceEvaluationContext {
						ProductIds = allProductIds,
						PricelistIds = pricelistId == null ? null : new string[] { pricelistId },
						Currency = currency
					};

					var allProductPrices = _pricingService.EvaluateProductPrices(priceEvalContext).ToArray();
					foreach(var product in products)
					{
						product.Prices = allProductPrices.Where(x => x.ProductId == product.Id).ToList();
					}
					//Load inventories
					notification.Description = "loading inventory information...";
					_notifier.Upsert(notification);
					var allProductInventories = _inventoryService.GetProductsInventoryInfos(allProductIds);
					foreach (var product in products)
					{
						product.Inventories = allProductInventories.Where(x => x.ProductId == product.Id)
							.Where(x => fulfilmentCenterId == null ? true : x.FulfillmentCenterId == fulfilmentCenterId).ToList();
					}

					notification.TotalCount = products.Count();
					//populate export configuration
					Dictionary<string, Func<CatalogProduct, string>> exportConfiguration = new Dictionary<string, Func<CatalogProduct, string>>();
					PopulateProductExportConfiguration(exportConfiguration, products);

					//Write header
					foreach (var cfgItem in exportConfiguration)
					{
						csvWriter.WriteField(cfgItem.Key);
					}
					csvWriter.NextRecord();

					var notifyProductSizeLimit = 50;
					var counter = 0;
					//Write products
					foreach (var product in products)
					{
						if(catalogName == null && product.Catalog != null)
						{
							catalogName = product.Catalog.Name;
						}

						try
						{
							foreach (var cfgItem in exportConfiguration)
							{
								var fieldValue = String.Empty;
								if (cfgItem.Value == null)
								{
									var propertyInfo = productPropertyInfos.FirstOrDefault(x => x.Name == cfgItem.Key);
									if (propertyInfo != null)
									{
										var objValue = propertyInfo.GetValue(product);
										fieldValue = objValue != null ? objValue.ToString() : fieldValue;
									}
								}
								else
								{
									fieldValue = cfgItem.Value(product);
								}
								csvWriter.WriteField(fieldValue);
							}
							csvWriter.NextRecord();
						}
						catch(Exception ex)
						{
							notification.ErrorCount++;
							notification.Errors.Add(ex.ToString());
							_notifier.Upsert(notification);
						}

						//Raise notification each notifyProductSizeLimit products
						counter++;
						notification.ProcessedCount = counter;
						notification.Description = string.Format("{0} of {1} products processed", notification.ProcessedCount, notification.TotalCount);
						if (counter % notifyProductSizeLimit == 0)
						{
							_notifier.Upsert(notification);
						}
					}
					memoryStream.Position = 0;
					//Upload result csv to blob storage
					var uploadInfo = new UploadStreamInfo
					{
						FileName = "Catalog-" + (catalogName ?? catalogId) + "-export.csv",
						FileByteStream = memoryStream,
						FolderName = "temp"
					};
					var blobKey = _blobStorageProvider.Upload(uploadInfo);
					//Get a download url
					notification.DownloadUrl = _blobUrlResolver.GetAbsoluteUrl(blobKey);
					notification.Description = "Export finished";
				}
				catch(Exception ex)
				{
					notification.Description = "Export error";
					notification.ErrorCount++;
					notification.Errors.Add(ex.ToString());
				}
				finally
				{
					notification.Finished = DateTime.UtcNow;
					_notifier.Upsert(notification);
				}
		
			}
			
		}
		 public void PlatformExportBackground(PlatformExportImportRequest exportRequest, string platformVersion, string author, ExportImportProgressNotificationEvent notifyEvent)
		 {
			 Action<ExportImportProgressInfo> progressCallback = (x) =>
			 {
				 notifyEvent.InjectFrom(x);
				 _eventNotifier.Upsert(notifyEvent);
			 };

			 var now = DateTime.UtcNow;
			 try
			 {
				 var exportedModules = InnerGetModulesWithInterface(typeof(ISupportExportModule)).Where(x => exportRequest.Modules.Contains(x.Id)).ToArray();
				 using (var stream = new MemoryStream())
				 {
					 var options = new PlatformExportImportOptions
					 {
						 Modules = exportedModules,
						 PlatformSecurity = exportRequest.PlatformSecurity,
						 PlatformSettings = exportRequest.PlatformSettings,
						 PlatformVersion = SemanticVersion.Parse(platformVersion),
						 Author = author
					 };

					 _platformExportManager.Export(stream, options, progressCallback);
					 stream.Seek(0, SeekOrigin.Begin);
					 //Upload result  to blob storage
					 var uploadInfo = new UploadStreamInfo
					 {
						 FileName = "Platform-" + now.ToString("yyMMddhh") + "-export.zip",
						 FileByteStream = stream,
						 FolderName = "tmp"
					 };
					 var blobKey = _blobStorageProvider.Upload(uploadInfo);
					 //Get a download url
					 notifyEvent.DownloadUrl = _blobUrlResolver.GetAbsoluteUrl(blobKey);
					 notifyEvent.Description = "Export finished";
				 }
			 }
			 catch(Exception ex)
			 {
				 notifyEvent.Errors.Add(ex.ExpandExceptionMessage()); 
			 }
			 finally
			 {
				 notifyEvent.Finished = DateTime.UtcNow;
				 _eventNotifier.Upsert(notifyEvent);
			 }

		 }
        // Only public methods can be invoked in the background. (Hangfire)
        public void BackgroundExport(CsvExportInfo exportInfo, ExportNotification notifyEvent)
		{
			var curencySetting = _settingsManager.GetSettingByName("VirtoCommerce.Core.General.Currencies");
			var defaultCurrency = EnumUtility.SafeParse<CurrencyCodes>(curencySetting.DefaultValue, CurrencyCodes.USD);
			exportInfo.Currency = exportInfo.Currency ?? defaultCurrency;
			var catalog = _catalogService.GetById(exportInfo.CatalogId);
			if (catalog == null)
			{
				throw new NullReferenceException("catalog");
			}
			
			 Action<ExportImportProgressInfo> progressCallback = (x) =>
			 {
				 notifyEvent.InjectFrom(x);
				 _notifier.Upsert(notifyEvent);
			 };

			 using (var stream = new MemoryStream())
			 {
				 try
				 {
					 exportInfo.Configuration = CsvProductMappingConfiguration.GetDefaultConfiguration();
					 _csvExporter.DoExport(stream, exportInfo, progressCallback);
					 
					 stream.Position = 0;
					 //Upload result csv to blob storage
					 var uploadInfo = new UploadStreamInfo
					 {
						 FileName = "Catalog-" + catalog.Name + "-export.csv",
						 FileByteStream = stream,
						 FolderName = "temp"
					 };
					 var blobKey = _blobStorageProvider.Upload(uploadInfo);
					 //Get a download url
					 notifyEvent.DownloadUrl = _blobUrlResolver.GetAbsoluteUrl(blobKey);
					 notifyEvent.Description = "Export finished";
				 }
				 catch (Exception ex)
				 {
					 notifyEvent.Description = "Export failed";
					 notifyEvent.Errors.Add(ex.ExpandExceptionMessage());
				 }
				 finally
				 {
					 notifyEvent.Finished = DateTime.UtcNow;
					 _notifier.Upsert(notifyEvent);
				 }
			 }
			
		}
        public void PlatformExportBackground(PlatformImportExportRequest exportRequest, PlatformExportPushNotification pushNotification)
        {
            Action<ExportImportProgressInfo> progressCallback = (x) =>
            {
                pushNotification.InjectFrom(x);
                pushNotification.Errors = x.Errors;
                _pushNotifier.Upsert(pushNotification);
            };

            try
            {
                using (var stream = new MemoryStream())
                {
                    var manifest = exportRequest.ToManifest();
                    _platformExportManager.Export(stream, manifest, progressCallback);
                    stream.Seek(0, SeekOrigin.Begin);
                    //Upload result  to blob storage
                    var uploadInfo = new UploadStreamInfo
                    {
                        FileName = string.Format("exported_data.zip"),
                        FileByteStream = stream,
                        FolderName = "tmp"
                    };
                    var blobKey = _blobStorageProvider.Upload(uploadInfo);
                    //Get a download url
                    pushNotification.DownloadUrl = _blobUrlResolver.GetAbsoluteUrl(blobKey);
                }
            }
            catch (Exception ex)
            {
                pushNotification.Errors.Add(ex.ExpandExceptionMessage());
            }
            finally
            {
                pushNotification.Description = "Export finished";
                pushNotification.Finished = DateTime.UtcNow;
                _pushNotifier.Upsert(pushNotification);
            }

        }