/// <summary>
        /// 已经存在物理文件,添加媒体文件信息。
        /// </summary>
        /// <param name="storage">物理文件存储信息。</param>
        /// <param name="extension">扩展名。</param>
        /// <param name="title">标题。</param>
        /// <param name="isUnique">判断每个物理文件和媒体文件信息是否一一对应。</param>
        /// <param name="mediaType">媒体类型。</param>
        /// <param name="targetId">所属实例Id。</param>
        /// <param name="directoryId">文件目录Id。</param>
        /// <returns>返回当前文件的访问地址,如果失败返回<c>null</c>。</returns>
        private async Task <string> CreateAsync(StorageFileInfo storage, string extension, string title, bool isUnique, string mediaType, int targetId, int directoryId)
        {
            var mediaFile = await _repository.FindAsync(m => m.FileId == storage.FileId);

            if (mediaFile != null && isUnique)
            {
                return(mediaFile.Url);
            }
            if (string.IsNullOrWhiteSpace(extension))
            {
                extension = ".png";
            }
            mediaFile             = new MediaFileInfo();
            mediaFile.Id          = Guid.NewGuid();
            mediaFile.Extension   = extension;
            mediaFile.Type        = mediaType;
            mediaFile.TargetId    = targetId;
            mediaFile.DirectoryId = directoryId;
            mediaFile.Length      = storage.Length;
            mediaFile.FileId      = storage.FileId;
            mediaFile.Title       = title;
            if (await _repository.CreateAsync(mediaFile))
            {
                return(mediaFile.Url);
            }
            return(null);
        }
        /// <summary>
        /// 从临时文件中的文件全新添加文件信息。
        /// </summary>
        /// <param name="path">临时文件的物理路径。</param>
        /// <param name="md5">文件Md5值。</param>
        /// <param name="extension">扩展名称。</param>
        /// <param name="title">标题。</param>
        /// <param name="contentType">内容类型。</param>
        /// <param name="length">大小。</param>
        /// <param name="mediaType">媒体类型。</param>
        /// <param name="targetId">所属实例Id。</param>
        /// <param name="directoryId">文件目录Id。</param>
        /// <param name="mediaId">媒体文件的Id。</param>
        /// <returns>返回当前文件的访问地址,如果失败返回<c>null</c>。</returns>
        private async Task <string> CreateAsync(string path, string md5, string extension, string title, string contentType, long length, string mediaType, int targetId, int directoryId, Guid?mediaId = null)
        {
            var storage   = new StorageFileInfo();
            var mediaFile = new MediaFileInfo();

            mediaFile.Id = mediaId ?? Guid.NewGuid();
            if (await _repository.BeginTransactionAsync(async db =>
            {
                var storages = db.As <StorageFileInfo>();
                storage.Name = md5;
                storage.Length = length;
                storage.ContentType = contentType ?? ContentType.GetContentType(extension);
                if (await storages.CreateAsync(storage))
                {
                    mediaFile.Title = title;
                    mediaFile.Extension = extension;
                    mediaFile.Type = mediaType;
                    mediaFile.TargetId = targetId;
                    mediaFile.DirectoryId = directoryId;
                    mediaFile.Length = length;
                    mediaFile.FileId = storage.FileId;
                    return(await db.CreateAsync(mediaFile));
                }
                return(false);
            }))
            {
                StoredFile(path, storage);
                return(mediaFile.Url);
            }
            File.Delete(path);
            return(null);
        }
        private void StoredFile(string path, StorageFileInfo storage)
        {
            var mediaPath = GetMediaPath(storage);

            if (File.Exists(mediaPath))
            {//文件已经存在,但是数据库重建就会出现重复文件的事情
                File.Delete(path);
                return;
            }
            var dir = Path.GetDirectoryName(mediaPath);

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            File.Move(path, mediaPath);
        }
        /// <summary>
        /// 上传一个新的文件替换原来的物理文件。
        /// </summary>
        /// <param name="mediaFile">媒体文件实例对象。</param>
        /// <param name="path">临时文件物理路径。</param>
        /// <param name="file">表单文件实例对象。</param>
        /// <returns>返回文件的访问地址,如果不成功则返回<c>null</c>。</returns>
        private async Task <string> CreateAsync(MediaFileInfo mediaFile, string path, IFormFile file)
        {
            var md5     = Md5(path);
            var storage = await _storages.FindAsync(s => s.Name == md5);

            if (storage != null)
            {
                mediaFile.FileId = storage.FileId;
                mediaFile.Length = storage.Length;
                if (await _repository.UpdateAsync(f => f.Id == mediaFile.Id, new { mediaFile.Length, mediaFile.FileId }))
                {
                    return(mediaFile.Url);
                }
                return(null);
            }
            storage = new StorageFileInfo();
            if (await _repository.BeginTransactionAsync(async db =>
            {
                var storages = db.As <StorageFileInfo>();
                storage.Name = md5;
                storage.Length = file.Length;
                storage.ContentType = file.ContentType;
                if (await storages.CreateAsync(storage))
                {
                    mediaFile.Length = file.Length;
                    mediaFile.FileId = storage.FileId;
                    return(await db.UpdateAsync(f => f.Id == mediaFile.Id, new { mediaFile.Length, mediaFile.FileId }));
                }
                return(false);
            }))
            {
                StoredFile(path, storage);
                return(mediaFile.Url);
            }
            File.Delete(path);
            return(null);
        }
 private string GetMediaPath(StorageFileInfo storage)
 {
     return(Path.Combine(_mediaRootPath, storage.Path));
 }