Browse Source

增加文件存储模块,集成七牛云存储

pull/3/head
cKey 6 years ago
parent
commit
d15ed558bb
  1. 16
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN.Abp.FileStorage.Qiniu.csproj
  2. 10
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN/Abp/FileStorage/Qiniu/AbpQiniuFileStorageModule.cs
  3. 40
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN/Abp/FileStorage/Qiniu/QiniuFileStorageOptions.cs
  4. 111
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN/Abp/FileStorage/Qiniu/QiniuFileStorageProvider.cs
  5. 12
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN.Abp.FileStorage.csproj
  6. 8
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/AbpFileStorageModule.cs
  7. 8
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileDownloadCompletedEventArges.cs
  8. 11
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileDownloadProgressEventArges.cs
  9. 59
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileInfo.cs
  10. 63
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileStorageProvider.cs
  11. 8
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileUploadCompletedEventArges.cs
  12. 21
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileUploadProgressEventArges.cs
  13. 41
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/IFileStorageProvider.cs
  14. 39
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/IFileStore.cs
  15. 25
      aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/MediaType.cs

16
aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN.Abp.FileStorage.Qiniu.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Qiniu.Shared" Version="7.2.15" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.FileStorage\LINGYUN.Abp.FileStorage.csproj" />
</ItemGroup>
</Project>

10
aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN/Abp/FileStorage/Qiniu/AbpQiniuFileStorageModule.cs

@ -0,0 +1,10 @@
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.FileStorage.Qiniu
{
[DependsOn(typeof(AbpFileStorageModule))]
public class AbpQiniuFileStorageModule : AbpModule
{
}
}

40
aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN/Abp/FileStorage/Qiniu/QiniuFileStorageOptions.cs

@ -0,0 +1,40 @@
namespace LINGYUN.Abp.FileStorage.Qiniu
{
public class QiniuFileStorageOptions
{
/// <summary>
/// Api授权码
/// </summary>
public string AccessKey { get; set; }
/// <summary>
/// Api密钥
/// </summary>
public string SecretKey { get; set; }
/// <summary>
/// 默认自动删除该文件天数
/// 默认 0,不删除
/// </summary>
public int DeleteAfterDays { get; set; }
/// <summary>
/// 上传成功后,七牛云向业务服务器发送 POST 请求的 URL。
/// 必须是公网上可以正常进行 POST 请求并能响应 HTTP/1.1 200 OK 的有效 URL
/// </summary>
public string UploadCallbackUrl { get; set; }
/// <summary>
/// 上传成功后,七牛云向业务服务器发送回调通知时的 Host 值。
/// 与 callbackUrl 配合使用,仅当设置了 callbackUrl 时才有效。
/// </summary>
public string UploadCallbackHost { get; set; }
/// <summary>
/// 上传成功后,七牛云向业务服务器发送回调通知 callbackBody 的 Content-Type。
/// 默认为 application/x-www-form-urlencoded,也可设置为 application/json。
/// </summary>
public string UploadCallbackBodyType { get; set; }
/// <summary>
/// 上传成功后,自定义七牛云最终返回給上传端(在指定 returnUrl 时是携带在跳转路径参数中)的数据。
/// 支持魔法变量和自定义变量。returnBody 要求是合法的 JSON 文本。
/// 例如 {"key": $(key), "hash": $(etag), "w": $(imageInfo.width), "h": $(imageInfo.height)}。
/// </summary>
public string UploadCallbackBody { get; set; }
}
}

111
aspnet-core/modules/common/LINGYUN.Abp.FileStorage.Qiniu/LINGYUN/Abp/FileStorage/Qiniu/QiniuFileStorageProvider.cs

@ -0,0 +1,111 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Qiniu.IO;
using Qiniu.IO.Model;
using Qiniu.RS;
using Qiniu.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.FileStorage.Qiniu
{
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
[ExposeServices(typeof(IFileStorageProvider), typeof(FileStorageProvider))]
public class QiniuFileStorageProvider : FileStorageProvider
{
protected QiniuFileStorageOptions Options { get; }
public QiniuFileStorageProvider(
IFileStore store,
IOptions<QiniuFileStorageOptions> options)
: base(store)
{
Options = options.Value;
}
protected override async Task<FileInfo> DownloadFileAsync(FileInfo fileInfo, string saveLocalPath)
{
Mac mac = new Mac(Options.AccessKey, Options.SecretKey);
int expireInSeconds = 3600;
string accUrl = DownloadManager.CreateSignedUrl(mac, fileInfo.Url, expireInSeconds);
var saveLocalFile = Path.Combine(saveLocalPath, fileInfo.Name);
var httpResult = await DownloadManager.DownloadAsync(accUrl, saveLocalFile);
if(httpResult.Code == 200)
{
using (var fs = new FileStream(saveLocalFile, FileMode.Open, FileAccess.Read))
{
fileInfo.Data = new byte[fs.Length];
await fs.ReadAsync(fileInfo.Data, 0, fileInfo.Data.Length).ConfigureAwait(false);
}
}
else
{
// TODO: 处理响应代码
Console.WriteLine(httpResult.Code);
}
return fileInfo;
}
protected override async Task RemoveFileAsync(FileInfo fileInfo, CancellationToken cancellationToken = default)
{
Mac mac = new Mac(Options.AccessKey, Options.SecretKey);
var bucket = fileInfo.Directory + ":" + fileInfo.Name;
var backetManager = new BucketManager(mac);
await backetManager.DeleteAsync(bucket, fileInfo.Name);
throw new NotImplementedException();
}
protected override async Task UploadFileAsync(FileInfo fileInfo, int? expireIn = null, CancellationToken cancellationToken = default)
{
Mac mac = new Mac(Options.AccessKey, Options.SecretKey);
PutPolicy putPolicy = new PutPolicy
{
Scope = fileInfo.Directory + ":" + fileInfo.Name,
CallbackBody = Options.UploadCallbackBody,
CallbackBodyType = Options.UploadCallbackBodyType,
CallbackHost = Options.UploadCallbackHost,
CallbackUrl = Options.UploadCallbackUrl
};
if (expireIn.HasValue)
{
putPolicy.SetExpires(expireIn.Value);
}
if (Options.DeleteAfterDays > 0)
{
putPolicy.DeleteAfterDays = Options.DeleteAfterDays;
}
string jstr = putPolicy.ToJsonString();
string token = Auth.CreateUploadToken(mac, jstr);
UploadProgressHandler handler = (uploadByte, totalByte) =>
{
OnFileUploadProgressChanged(uploadByte, totalByte);
};
// 带进度的上传
ResumableUploader uploader = new ResumableUploader();
var httpResult = await uploader.UploadDataAsync(fileInfo.Data, fileInfo.Name, token, handler);
// 普通上传
//FormUploader fu = new FormUploader();
//var httpResult = await fu.UploadDataAsync(fileInfo.Data, fileInfo.Name, token);
// TODO: 处理响应代码
Console.WriteLine(httpResult.Code);
}
}
}

12
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN.Abp.FileStorage.csproj

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Core" Version="2.8.0" />
</ItemGroup>
</Project>

8
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/AbpFileStorageModule.cs

@ -0,0 +1,8 @@
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.FileStorage
{
public class AbpFileStorageModule : AbpModule
{
}
}

8
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileDownloadCompletedEventArges.cs

@ -0,0 +1,8 @@
using System;
namespace LINGYUN.Abp.FileStorage
{
public class FileDownloadCompletedEventArges : EventArgs
{
}
}

11
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileDownloadProgressEventArges.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace LINGYUN.Abp.FileStorage
{
public class FileDownloadProgressEventArges : EventArgs
{
}
}

59
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileInfo.cs

@ -0,0 +1,59 @@
using System;
namespace LINGYUN.Abp.FileStorage
{
/// <summary>
/// 文件信息
/// </summary>
public class FileInfo
{
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 大小
/// </summary>
public long Size { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string Directory { get; set; }
/// <summary>
/// 文件扩展名
/// </summary>
public string Extension { get; set; }
/// <summary>
/// 文件哈希码,用于唯一标识
/// </summary>
public string Hash { get; set; }
/// <summary>
/// 文件链接
/// </summary>
public string Url { get; set; }
/// <summary>
/// 文件数据
/// </summary>
public byte[] Data { get; set; }
/// <summary>
/// 媒体类型
/// </summary>
public MediaType MediaType { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreationTime { get; set; }
/// <summary>
/// 创建人
/// </summary>
public Guid? CreatorId { get; set; }
/// <summary>
/// 上次变更时间
/// </summary>
public DateTime? LastModificationTime { get; set; }
/// <summary>
/// 上次变更人
/// </summary>
public Guid? LastModifierId { get; set; }
}
}

63
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileStorageProvider.cs

@ -0,0 +1,63 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.FileStorage
{
public abstract class FileStorageProvider : IFileStorageProvider
{
public event EventHandler<FileDownloadProgressEventArges> FileDownloadProgressChanged;
public event EventHandler<FileDownloadCompletedEventArges> FileDownloadCompleted;
public event EventHandler<FileUploadProgressEventArges> FileUploadProgressChanged;
public event EventHandler<FileUploadCompletedEventArges> FileUploadCompleted;
protected IFileStore Store { get; }
public FileStorageProvider(IFileStore store)
{
Store = store;
}
public async Task DeleteFileAsync(string hash, CancellationToken cancellationToken = default)
{
// 获取文件信息
var file = await Store.GetFileAsync(hash);
// 删除文件
await RemoveFileAsync(file, cancellationToken);
// 删除文件信息
await Store.DeleteFileAsync(hash, cancellationToken);
}
public async Task<FileInfo> GetFileAsync(string hash, string saveLocalPath)
{
// 获取文件信息
var file = await Store.GetFileAsync(hash);
// 下载文件
return await DownloadFileAsync(file, saveLocalPath);
}
public async Task StorageAsync(FileInfo fileInfo, int? expireIn = null, CancellationToken cancellationToken = default)
{
// step1 上传文件
await UploadFileAsync(fileInfo, expireIn, cancellationToken);
// step2 保存文件信息
await Store.StorageAsync(fileInfo, expireIn, cancellationToken);
}
protected abstract Task UploadFileAsync(FileInfo fileInfo, int? expireIn = null, CancellationToken cancellationToken = default);
protected abstract Task<FileInfo> DownloadFileAsync(FileInfo fileInfo, string saveLocalPath);
protected abstract Task RemoveFileAsync(FileInfo fileInfo, CancellationToken cancellationToken = default);
protected virtual void OnFileUploadProgressChanged(long sent, long total)
{
FileUploadProgressChanged?.Invoke(this, new FileUploadProgressEventArges(sent, total));
}
protected virtual void OnFileUploadConpleted()
{
FileUploadCompleted?.Invoke(this, new FileUploadCompletedEventArges());
}
}
}

8
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileUploadCompletedEventArges.cs

@ -0,0 +1,8 @@
using System;
namespace LINGYUN.Abp.FileStorage
{
public class FileUploadCompletedEventArges : EventArgs
{
}
}

21
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/FileUploadProgressEventArges.cs

@ -0,0 +1,21 @@
using System;
namespace LINGYUN.Abp.FileStorage
{
public class FileUploadProgressEventArges : EventArgs
{
/// <summary>
/// 上传数据大小
/// </summary>
public long BytesSent { get; }
/// <summary>
/// 总数据大小
/// </summary>
public long TotalBytesSent { get; }
public FileUploadProgressEventArges(long sent, long total)
{
BytesSent = sent;
TotalBytesSent = total;
}
}
}

41
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/IFileStorageProvider.cs

@ -0,0 +1,41 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.FileStorage
{
/// <summary>
/// 文件存储提供者
/// </summary>
public interface IFileStorageProvider
{
event EventHandler<FileDownloadProgressEventArges> FileDownloadProgressChanged;
event EventHandler<FileDownloadCompletedEventArges> FileDownloadCompleted;
event EventHandler<FileUploadProgressEventArges> FileUploadProgressChanged;
event EventHandler<FileUploadCompletedEventArges> FileUploadCompleted;
/// <summary>
/// 存储文件
/// </summary>
/// <param name="fileInfo">文件信息</param>
/// <param name="expireIn">过期时间,单位(s)</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task StorageAsync(FileInfo fileInfo, int? expireIn = null, CancellationToken cancellationToken = default);
/// <summary>
/// 获取文件
/// </summary>
/// <param name="hash">文件唯一标识</param>
/// <param name="saveLocalPath">保存到本地路径</param>
/// <returns></returns>
Task<FileInfo> GetFileAsync(string hash, string saveLocalPath);
/// <summary>
/// 删除文件
/// </summary>
/// <param name="hash">文件唯一标识</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task DeleteFileAsync(string hash, CancellationToken cancellationToken = default);
}
}

39
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/IFileStore.cs

@ -0,0 +1,39 @@
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.FileStorage
{
/// <summary>
/// 文件存储接口
/// </summary>
public interface IFileStore
{
/// <summary>
/// 存储文件
/// </summary>
/// <param name="fileInfo">文件信息</param>
/// <param name="expireIn">过期时间,单位(s)</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task StorageAsync(FileInfo fileInfo, int? expireIn = null, CancellationToken cancellationToken = default);
/// <summary>
/// 获取文件
/// </summary>
/// <param name="hash">文件唯一标识</param>
/// <returns></returns>
Task<FileInfo> GetFileAsync(string hash);
/// <summary>
/// 文件是否存在
/// </summary>
/// <param name="hash">文件唯一标识</param>
/// <returns></returns>
Task<bool> FileHasExistsAsync(string hash);
/// <summary>
/// 删除文件
/// </summary>
/// <param name="hash">文件唯一标识</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task DeleteFileAsync(string hash, CancellationToken cancellationToken = default);
}
}

25
aspnet-core/modules/common/LINGYUN.Abp.FileStorage/LINGYUN/Abp/FileStorage/MediaType.cs

@ -0,0 +1,25 @@
namespace LINGYUN.Abp.FileStorage
{
/// <summary>
/// 媒体类型
/// </summary>
public enum MediaType
{
/// <summary>
/// 文档
/// </summary>
Document = 0,
/// <summary>
/// 图像
/// </summary>
Image = 2,
/// <summary>
/// 影像
/// </summary>
Video = 3,
/// <summary>
/// 音乐
/// </summary>
Music = 4
}
}
Loading…
Cancel
Save