Files
FileServices/Qiniu/FileService.cs

195 lines
8.6 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Qiniu.Http;
using Qiniu.Storage;
using Qiniu.Util;
using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Ufangx.FileServices.Abstractions;
using Microsoft.Extensions.DependencyInjection;
namespace Qiniu
{
public class FileService : IFileService
{
protected readonly FileServiceOptions options;
protected readonly Mac mac;
protected readonly Config config;
protected readonly IHttpContextAccessor contextAccessor;
public FileService(IOptions<FileServiceOptions> options, IHttpContextAccessor contextAccessor)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
this.options = options.Value;
mac = new Mac(this.options.AccessKey, this.options.SecretKey);
config = new Config();
config.UseHttps = this.options.UseHttps;
config.UseCdnDomains = this.options.UseCdnDomains;
config.ChunkSize = this.options.ChunkUnit;
if (this.options.PutThreshold.HasValue)
{
config.PutThreshold = this.options.PutThreshold.Value;
}
if (this.options.MaxRetryTimes.HasValue)
{
config.MaxRetryTimes = this.options.MaxRetryTimes.Value;
}
if (!string.IsNullOrWhiteSpace(this.options.Zone))
{
switch (this.options.Zone.ToLower())
{
case "zonecneast":
config.Zone = Zone.ZoneCnEast;
//config.Zone = Zone.ZONE_CN_East;
break;
case "zonecnnorth":
config.Zone = Zone.ZoneCnNorth;
//config.Zone = Zone.ZONE_CN_North;
break;
case "zonecnsouth":
config.Zone = Zone.ZoneCnSouth;
//config.Zone = Zone.ZONE_CN_South;
break;
case "zoneusnorth":
config.Zone = Zone.ZoneUsNorth;
//config.Zone = Zone.ZONE_US_North;
break;
case "zoneassingapore":
config.Zone = Zone.ZoneAsSingapore;
//config.Zone = Zone.ZONE_AS_Singapore;
break;
default:
config.Zone = Newtonsoft.Json.JsonConvert.DeserializeObject<Zone>(this.options.Zone);
break;
}
}
this.contextAccessor = contextAccessor;
}
public Task<bool> Append(string path, Stream stream, CancellationToken token = default)
{
//var key = GetSaveKey(path);
//if (stream.CanSeek && stream.Position > 0) { stream.Position = 0; }
//ResumableUploader resumableUploader = new ResumableUploader(config);
//var result = await
// resumableUploader.UploadStream(stream, key, GetToken(key), null);
// //Task.FromResult(resumableUploader.UploadStream(stream, key, GetToken(key), null));
//return result.Code == (int)HttpCode.OK;
throw new NotSupportedException();
}
public async Task<bool> Append(string path, byte[] data, CancellationToken token = default)
=> await Append(path, new MemoryStream(data), token);
public async Task<bool> Delete(string path, CancellationToken token = default)
=> (await GetBucketManager().Delete(options.Bucket,await GetSaveKey(path))).Code == (int)HttpCode.OK;
//(await Task.FromResult(GetBucketManager().Delete(options.Bucket, GetSaveKey(path)))).Code == (int)HttpCode.OK;
public async Task<bool> Exists(string path, CancellationToken token = default)
{
var result = await GetInfo(path);
return result.Code == (int)HttpCode.OK;
}
async Task<string> GetDownloadUrl(string path)
{
var key =await GetSaveKey(path);
string baseUrl = options.Domain.Trim();
baseUrl = baseUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || baseUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ? baseUrl :
"http://" + baseUrl;
var privateUrl = DownloadManager.CreatePrivateUrl(mac, baseUrl, key, 3600);
return privateUrl;
}
public async Task<byte[]> GetFileData(string path, CancellationToken token = default)
{
var url =await GetDownloadUrl(path);
HttpClient client = new HttpClient();
return await client.GetByteArrayAsync(url);
}
async Task<StatResult> GetInfo(string path) => await
GetBucketManager().Stat(options.Bucket,await GetSaveKey(path));
//Task.FromResult(GetBucketManager().Stat(options.Bucket, GetSaveKey(path)));
public async Task<DateTime> GetModifyDate(string path, CancellationToken token = default)
{
var result = await GetInfo(path);
if (result.Code == (int)HttpCode.OK)
{
return new DateTime(result.Result.PutTime);
}
throw new Exception(result.Text);
}
public async Task<Stream> GetStream(string path, CancellationToken token = default)
{
var url =await GetDownloadUrl(path);
HttpClient client = new HttpClient();
return await client.GetStreamAsync(url);
}
BucketManager GetBucketManager() => new BucketManager(mac, config);
public async Task Move(string sourceFileName, string destFileName)
{
BucketManager bucket = GetBucketManager();
//var result = await Task.FromResult(bucket.Move(options.Bucket, GetSaveKey(sourceFileName), options.Bucket, GetSaveKey(destFileName)));
var result = await bucket.Move(options.Bucket,await GetSaveKey(sourceFileName), options.Bucket,await GetSaveKey(destFileName));
if (result.Code != (int)HttpCode.OK)
{
throw new Exception(result.Text);
}
}
Task<string> GetSaveKey(string path)
{
return contextAccessor.GetSaveKey(options.BasePath, path);
}
string GetToken(string savekey)
{
return Utils.GetToken(savekey, options.AccessKey, options.SecretKey, options.Bucket);
//Mac mac = new Mac(options.AccessKey, options.SecretKey);
//PutPolicy putPolicy = new PutPolicy();
//// 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖),请使用 SCOPE = "BUCKET:KEY"
//putPolicy.Scope = $"{options.Bucket}:{savekey}";
////putPolicy.Scope = options.Bucket;
//// 上传策略有效期(对应于生成的凭证的有效期)
//putPolicy.SetExpires(3600);
//// 上传到云端多少天后自动删除该文件,如果不设置(即保持默认默认)则不删除
////putPolicy.DeleteAfterDays = 1;
//// 生成上传凭证,参见
//// https://developer.qiniu.com/kodo/manual/upload-token
//string jstr = putPolicy.ToJsonString();
//var token = Auth.CreateUploadToken(mac, jstr);
//return token;
}
UploadManager GetUploadManager()
{
return new UploadManager(config);
}
public async Task<bool> Save(string path, Stream stream, CancellationToken token = default)
{
if (stream == null || stream.Length == 0) return false;
if (stream.CanSeek && stream.Position > 0) { stream.Position = 0; }
byte[] data = new byte[stream.Length];
await stream.ReadAsync(data, 0, data.Length);
return await Save(path, data, token);
//不能用UploadStream方法因为方法里面会释放掉数据流数据量在作用域内释放会导致很多问题
}
public async Task<bool> Save(string path, byte[] data, CancellationToken token = default)
{
var key =await GetSaveKey(path);
var uploadManager = GetUploadManager();
//var result = await Task.FromResult(uploadManager.UploadData(data, key, GetToken(key), null));
var result = await uploadManager.UploadData(data, key, GetToken(key), null);
return result.Code == (int)HttpCode.OK;
}
}
}