diff --git a/Directory.Packages.props b/Directory.Packages.props
index 7ef269c33..7c7d36b3d 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -354,6 +354,7 @@
+
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Aliyun/LINGYUN/Abp/BlobManagement/Aliyun/AliyunBlobProvider.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Aliyun/LINGYUN/Abp/BlobManagement/Aliyun/AliyunBlobProvider.cs
index 912320b7a..fa6af872e 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Aliyun/LINGYUN/Abp/BlobManagement/Aliyun/AliyunBlobProvider.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Aliyun/LINGYUN/Abp/BlobManagement/Aliyun/AliyunBlobProvider.cs
@@ -1,4 +1,5 @@
-using Aliyun.OSS;
+using AlibabaCloud.OSS.V2;
+using AlibabaCloud.OSS.V2.Models;
using LINGYUN.Abp.BlobStoring.Aliyun;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -50,23 +51,29 @@ public class AliyunBlobProvider : IBlobProvider
{
var client = await CreateClientAsync();
var bucket = NormalizeContainerName(name);
+ var configuration = GetBlobConfiguration();
- CreateBucketIfNotExists(client, bucket);
+ await CreateBucketIfNotExists(client, bucket, configuration.CreateBucketAcl, cancellationToken);
}
public async virtual Task DeleteContainerAsync(
string name,
CancellationToken cancellationToken = default)
{
- var client = await CreateClientAsync();
+ var ossClient = await CreateClientAsync();
var bucket = NormalizeContainerName(name);
- if (!BucketExists(client, bucket))
+ if (!await BucketExists(ossClient, bucket, cancellationToken))
{
return;
}
- client.DeleteBucket(bucket);
+ await ossClient.DeleteBucketAsync(
+ new DeleteBucketRequest
+ {
+ Bucket = bucket,
+ },
+ cancellationToken: cancellationToken);
}
public async virtual Task DeleteBlobAsync(
@@ -74,13 +81,19 @@ public class AliyunBlobProvider : IBlobProvider
string blobName,
CancellationToken cancellationToken = default)
{
- var client = await CreateClientAsync();
+ var ossClient = await CreateClientAsync();
var bucket = NormalizeContainerName(containerName);
var objectName = CalculateBlobName(blobName);
- if (ObjectExists(client, bucket, objectName))
+ if (await ObjectExists(ossClient, bucket, objectName, cancellationToken))
{
- client.DeleteObject(bucket, objectName);
+ await ossClient.DeleteObjectAsync(
+ new DeleteObjectRequest
+ {
+ Bucket = bucket,
+ Key = objectName,
+ },
+ cancellationToken: cancellationToken);
}
}
@@ -98,39 +111,75 @@ public class AliyunBlobProvider : IBlobProvider
string blobName,
CancellationToken cancellationToken = default)
{
- var configuration = GetBlobConfiguration();
+ var ossClient = await CreateClientAsync();
+ var bucket = NormalizeContainerName(containerName);
+ var objectName = CalculateBlobName(blobName);
- var downloadUrl = await GenerateDownloadUrlAsync(
- containerName,
- blobName,
- TimeSpan.FromSeconds(configuration.PresignedGetExpirySeconds),
- cancellationToken);
- if (downloadUrl.IsNullOrWhiteSpace())
+ if (!await ObjectExists(ossClient, bucket, objectName, cancellationToken))
{
return null;
}
- var httpClient = HttpClientFactory.CreateAliyunHttpClient();
+ var result = await ossClient.GetObjectAsync(
+ new GetObjectRequest
+ {
+ Bucket = bucket,
+ Key = blobName,
+ });
+
+ return result.Body;
- return await httpClient.GetStreamAsync(downloadUrl, cancellationToken);
+ // TODO: 阿里云sdk预签名不可用[2026/05/23]
+ //var configuration = GetBlobConfiguration();
+
+ //var downloadUrl = await GeneratePresignedUrlAsync(
+ // containerName,
+ // blobName,
+ // TimeSpan.FromSeconds(configuration.PresignedGetExpirySeconds),
+ // cancellationToken: cancellationToken);
+ //if (downloadUrl.IsNullOrWhiteSpace())
+ //{
+ // return null;
+ //}
+
+ //var httpClient = HttpClientFactory.CreateAliyunHttpClient();
+
+ //return await httpClient.GetStreamAsync(downloadUrl, cancellationToken);
}
- public async virtual Task GenerateDownloadUrlAsync(
+ public virtual Task GeneratePresignedUrlAsync(
string containerName,
string blobName,
TimeSpan expiration,
+ bool isAttachmentContent = true,
CancellationToken cancellationToken = default)
{
- var client = await CreateClientAsync();
- var bucket = NormalizeContainerName(containerName);
- var objectName = CalculateBlobName(blobName);
-
- if (!ObjectExists(client, bucket, objectName))
- {
- return null;
- }
-
- return client.GeneratePresignedUri(bucket, objectName, Clock.Now.Add(expiration)).ToString();
+ // TODO: 阿里云sdk预签名不可用[2026/05/23]
+ return Task.FromResult(null);
+ //var ossClient = await CreateClientAsync();
+ //var bucket = NormalizeContainerName(containerName);
+ //var objectName = CalculateBlobName(blobName);
+
+ //if (!await ObjectExists(ossClient, bucket, objectName, cancellationToken))
+ //{
+ // return null;
+ //}
+
+ //var fileName = Path.GetFileName(blobName);
+ //var type = isAttachmentContent ? "attachment" : "inline";
+ //var disposition = $"{type}; filename=\"{Uri.EscapeDataString(fileName)}\"; " +
+ // $"filename*=UTF-8''{Uri.EscapeDataString(fileName)}";
+
+ //var presignResult = ossClient.Presign(
+ // new GetObjectRequest
+ // {
+ // Bucket = bucket,
+ // Key = blobName,
+ // ResponseContentDisposition = disposition,
+ // },
+ // Clock.Now.Add(expiration));
+
+ //return presignResult.Url;
}
public virtual Task CreateFolderAsync(
@@ -150,49 +199,79 @@ public class AliyunBlobProvider : IBlobProvider
string? contentType = null,
CancellationToken cancellationToken = default)
{
- var client = await CreateClientAsync();
+ var ossClient = await CreateClientAsync();
var bucket = NormalizeContainerName(containerName);
var objectName = CalculateBlobName(blobName);
+ var configuration = GetBlobConfiguration();
- CreateBucketIfNotExists(client, bucket);
-
- var objectMetadata = new ObjectMetadata();
- if (!contentType.IsNullOrWhiteSpace())
- {
- objectMetadata.ContentType = contentType;
- }
-
- client.PutObject(bucket, objectName, content, objectMetadata);
+ await CreateBucketIfNotExists(ossClient, bucket, configuration.CreateBucketAcl, cancellationToken);
+
+ await ossClient.PutObjectAsync(
+ new PutObjectRequest
+ {
+ Bucket = bucket,
+ Key = objectName,
+ Body = content,
+ ContentType = contentType,
+ },
+ cancellationToken: cancellationToken);
}
protected virtual AliyunBlobProviderConfiguration GetBlobConfiguration()
{
var configuration = ConfigurationProvider.Get();
- var blobConfiguration = configuration.GetAliyunConfiguration();
- return blobConfiguration;
+ return configuration.GetAliyunConfiguration();
}
- protected async virtual Task CreateClientAsync()
+ protected async virtual Task CreateClientAsync()
{
- return await OssClientFactory.CreateAsync();
+ var configuration = GetBlobConfiguration();
+ return await OssClientFactory.CreateAsync(configuration);
}
- protected virtual void CreateBucketIfNotExists(IOss oss, string bucket)
+ protected async virtual Task CreateBucketIfNotExists(
+ Client ossClient,
+ string bucket,
+ BucketAclType? bucketAcl = null,
+ CancellationToken cancellationToken = default)
{
- if (!BucketExists(oss, bucket))
+ if (!await BucketExists(ossClient, bucket, cancellationToken))
{
- oss.CreateBucket(bucket);
+ await ossClient.PutBucketAsync(
+ new PutBucketRequest
+ {
+ Bucket = bucket,
+ },
+ cancellationToken: cancellationToken);
+
+ if (bucketAcl.HasValue)
+ {
+ await ossClient.PutBucketAclAsync(
+ new PutBucketAclRequest
+ {
+ Bucket = bucket,
+ Acl = bucketAcl.Value.GetString(),
+ },
+ cancellationToken: cancellationToken);
+ }
}
}
- protected virtual bool BucketExists(IOss oss, string bucket)
+ protected async virtual Task BucketExists(
+ Client ossClient,
+ string bucket,
+ CancellationToken cancellationToken = default)
{
- return oss.DoesBucketExist(bucket);
+ return await ossClient.IsBucketExistAsync(bucket, cancellationToken);
}
- protected virtual bool ObjectExists(IOss oss, string bucket, string objectName)
+ protected async virtual Task ObjectExists(
+ Client ossClient,
+ string bucket,
+ string objectName,
+ CancellationToken cancellationToken = default)
{
- return oss.DoesObjectExist(bucket, objectName);
+ return await ossClient.IsObjectExistAsync(bucket, objectName, cancellationToken: cancellationToken);
}
protected virtual string GetPrefixPath()
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByKeyInput.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByIdInput.cs
similarity index 69%
rename from aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByKeyInput.cs
rename to aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByIdInput.cs
index fb5da0020..4ac8d1f43 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByKeyInput.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByIdInput.cs
@@ -3,10 +3,10 @@ using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.BlobManagement.Dtos;
-public class BlobDownloadByKeyInput
+public class BlobDownloadByIdInput
{
public Guid? TenantId { get; set; }
[Required]
- public string Key { get; set; }
+ public Guid Id { get; set; }
}
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByNameInput.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByNameInput.cs
index 77715bb07..06663bc67 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByNameInput.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Dtos/BlobDownloadByNameInput.cs
@@ -1,10 +1,13 @@
-using System.ComponentModel.DataAnnotations;
+using System;
+using System.ComponentModel.DataAnnotations;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.BlobManagement.Dtos;
public class BlobDownloadByNameInput
{
+ public Guid? TenantId { get; set; }
+
[Required]
[DynamicStringLength(typeof(BlobContainerConsts), nameof(BlobContainerConsts.MaxNameLength))]
public string ContainerName { get; set; }
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IBlobAppService.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IBlobAppService.cs
index 2d4679569..4ed63da58 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IBlobAppService.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IBlobAppService.cs
@@ -17,13 +17,15 @@ public interface IBlobAppService : IApplicationService
Task DeleteAsync(Guid id);
+ Task GeneratePreviewUrlAsync(Guid id);
+
Task GenerateDownloadUrlAsync(Guid id);
- Task DownloadAsync(BlobDownloadByKeyInput input);
+ Task DownloadAsync(BlobDownloadByIdInput input);
- Task GetContentAsync(Guid id);
+ Task PreviewAsync(BlobDownloadByIdInput input);
- Task GetContentByNameAsync(BlobDownloadByNameInput input);
+ Task DownloadByNameAsync(BlobDownloadByNameInput input);
Task GetAsync(Guid id);
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IPrivateBlobAppService.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IPrivateBlobAppService.cs
index 9d25f2704..7164d938a 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IPrivateBlobAppService.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IPrivateBlobAppService.cs
@@ -17,9 +17,9 @@ public interface IPrivateBlobAppService : IApplicationService
Task DeleteAsync(Guid id);
- Task GetContentAsync(Guid id);
+ Task DownloadAsync(Guid id);
- Task GetContentByNameAsync(string name);
+ Task DownloadByNameAsync(string name);
Task GetAsync(Guid id);
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IPublicBlobAppService.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IPublicBlobAppService.cs
index dff540187..c381482c4 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IPublicBlobAppService.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/IPublicBlobAppService.cs
@@ -9,9 +9,9 @@ namespace LINGYUN.Abp.BlobManagement;
public interface IPublicBlobAppService : IApplicationService
{
- Task GetContentAsync(Guid id);
+ Task DownloadAsync(Guid id);
- Task GetContentByNameAsync(string name);
+ Task DownloadByNameAsync(string name);
Task GetAsync(Guid id);
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Integration/IBlobIntegrationService.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Integration/IBlobIntegrationService.cs
index 40a1fa835..ce105fec2 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Integration/IBlobIntegrationService.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application.Contracts/LINGYUN/Abp/BlobManagement/Integration/IBlobIntegrationService.cs
@@ -16,5 +16,5 @@ public interface IBlobIntegrationService : IApplicationService
Task ExistsAsync(BlobFileGetByNameIntegrationDto input);
- Task GetContentAsync(BlobFileGetByNameIntegrationDto input);
+ Task DownloadAsync(BlobFileGetByNameIntegrationDto input);
}
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppService.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppService.cs
index 689395ef4..ecafc86c1 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppService.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppService.cs
@@ -47,11 +47,30 @@ public class BlobAppService : BlobAppServiceBase, IBlobAppService
return await base.CreateFolderAsync(blobContainer, input);
}
- public async virtual Task GetContentByNameAsync(BlobDownloadByNameInput input)
+ public async virtual Task DownloadAsync(BlobDownloadByIdInput input)
{
- var blobContainer = await BlobContainerRepository.GetByNameAsync(input.ContainerName);
+ using (CurrentTenant.Change(input.TenantId ?? CurrentTenant.Id))
+ {
+ return await base.DownloadAsync(input.Id);
+ }
+ }
+
+ public async virtual Task PreviewAsync(BlobDownloadByIdInput input)
+ {
+ using (CurrentTenant.Change(input.TenantId ?? CurrentTenant.Id))
+ {
+ return await base.DownloadAsync(input.Id);
+ }
+ }
+
+ public async virtual Task DownloadByNameAsync(BlobDownloadByNameInput input)
+ {
+ using (CurrentTenant.Change(input.TenantId ?? CurrentTenant.Id))
+ {
+ var blobContainer = await BlobContainerRepository.GetByNameAsync(BlobManager.GetBlobProvider(), input.ContainerName);
- return await base.GetContentByNameAsync(blobContainer, input.BlobName);
+ return await base.DownloadByNameAsync(blobContainer, input.BlobName);
+ }
}
protected async override Task CheckGetPolicyAsync(string containerName, Blob blob)
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppServiceBase.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppServiceBase.cs
index 683e6b1ce..638234cf8 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppServiceBase.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobAppServiceBase.cs
@@ -48,43 +48,15 @@ public abstract class BlobAppServiceBase : BlobManagementApplicationService
public async virtual Task GenerateDownloadUrlAsync(Guid id)
{
- var blob = await BlobRepository.GetAsync(id);
- var blobContainer = await BlobContainerRepository.GetAsync(blob.ContainerId);
-
- await CheckGetPolicyAsync(blob);
-
- var fallbackUrlPrefix = blob.TenantId.HasValue
- ? $"/api/{BlobManagementRemoteServiceConsts.ModuleName}/blobs/download/t/{blob.TenantId:N}"
- : $"/api/{BlobManagementRemoteServiceConsts.ModuleName}/blobs/download";
-
- var downloadUrl = await BlobManager.GenerateDownloadUrlAsync(
- blobContainer,
- blob,
- fallbackUrlPrefix);
-
- return downloadUrl;
+ return await GenerateDownloadUrlAsync(id, "download");
}
- public async virtual Task DownloadAsync(BlobDownloadByKeyInput input)
+ public async virtual Task GeneratePreviewUrlAsync(Guid id)
{
- using (CurrentTenant.Change(input.TenantId))
- {
- var blob = await BlobManager.FindBlobByDownloadKeyAsync(input.Key);
- if (blob == null)
- {
- return new RemoteStreamContent(Stream.Null, input.Key);
- }
-
- // 临时下载链接一般用于临时预览与下载, 过期时间短, 不校验权限
- // await CheckGetPolicyAsync(blob);
-
- var stream = await BlobManager.DownloadBlobsync(blob);
-
- return new RemoteStreamContent(stream ?? Stream.Null, blob.Name, blob.ContentType, stream?.Length);
- }
+ return await GenerateDownloadUrlAsync(id, "preview", isAttachmentContent: false);
}
- public async virtual Task GetContentAsync(Guid id)
+ public async virtual Task DownloadAsync(Guid id)
{
var blob = await BlobRepository.GetAsync(id);
@@ -185,7 +157,7 @@ public abstract class BlobAppServiceBase : BlobManagementApplicationService
return ObjectMapper.Map(blob);
}
- protected async virtual Task GetContentByNameAsync(BlobContainer blobContainer, string name)
+ protected async virtual Task DownloadByNameAsync(BlobContainer blobContainer, string name)
{
var blob = await FindBlobByNameAsync(blobContainer, name)
?? throw new BusinessException(
@@ -200,6 +172,26 @@ public abstract class BlobAppServiceBase : BlobManagementApplicationService
return new RemoteStreamContent(stream ?? Stream.Null, blob.Name, blob.ContentType, stream?.Length);
}
+ protected async virtual Task GenerateDownloadUrlAsync(Guid id, string method, bool isAttachmentContent = true)
+ {
+ var blob = await BlobRepository.GetAsync(id);
+ var blobContainer = await BlobContainerRepository.GetAsync(blob.ContainerId);
+
+ await CheckGetPolicyAsync(blob);
+
+ var fallbackDownloadUrl = blob.TenantId.HasValue
+ ? $"/api/{BlobManagementRemoteServiceConsts.ModuleName}/blobs/{method}/t/{blob.TenantId:N}/{blob.Id:N}"
+ : $"/api/{BlobManagementRemoteServiceConsts.ModuleName}/blobs/{method}/{blob.Id:N}";
+
+ var downloadUrl = await BlobManager.GenerateDownloadUrlAsync(
+ blobContainer,
+ blob,
+ fallbackDownloadUrl,
+ isAttachmentContent);
+
+ return downloadUrl;
+ }
+
protected async virtual Task FindBlobByNameAsync(BlobContainer blobContainer, string name)
{
var blobName = HttpUtility.UrlDecode(name);
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobWithoutContainerAppService.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobWithoutContainerAppService.cs
index 66ed740d8..b4de50123 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobWithoutContainerAppService.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/BlobWithoutContainerAppService.cs
@@ -42,11 +42,11 @@ public abstract class BlobWithoutContainerAppService : BlobAppServiceBase
return await base.CreateFolderAsync(blobContainer, input);
}
- public async virtual Task GetContentByNameAsync(string name)
+ public async virtual Task DownloadByNameAsync(string name)
{
- var blobContainer = await BlobContainerRepository.GetByNameAsync(ContainerName);
+ var blobContainer = await BlobContainerRepository.GetByNameAsync(BlobManager.GetBlobProvider(), ContainerName);
- return await base.GetContentByNameAsync(blobContainer, name);
+ return await base.DownloadByNameAsync(blobContainer, name);
}
public async virtual Task> GetListAsync(BlobGetPagedListWithoutContainerInput input)
@@ -67,7 +67,7 @@ public abstract class BlobWithoutContainerAppService : BlobAppServiceBase
protected async virtual Task GetOrCreateContainer()
{
- var blobContainer = await BlobContainerRepository.FindByNameAsync(ContainerName)
+ var blobContainer = await BlobManager.FindContainerAsync(ContainerName)
?? await BlobManager.CreateContainerAsync(ContainerName);
return blobContainer;
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/Integration/BlobIntegrationService.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/Integration/BlobIntegrationService.cs
index 367da5ba9..b1c1cf24a 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/Integration/BlobIntegrationService.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Application/LINGYUN/Abp/BlobManagement/Integration/BlobIntegrationService.cs
@@ -28,7 +28,7 @@ public class BlobIntegrationService : BlobAppServiceBase, IBlobIntegrationServic
public async virtual Task CreateAsync(BlobFileCreateIntegrationDto input)
{
- var blobContainer = await BlobContainerRepository.GetByNameAsync(input.ContainerName);
+ var blobContainer = await BlobContainerRepository.GetByNameAsync(BlobManager.GetBlobProvider(), input.ContainerName);
// Example: /a/b/c/d/f.txt
var blobName = HttpUtility.UrlDecode(input.BlobName);
@@ -63,7 +63,7 @@ public class BlobIntegrationService : BlobAppServiceBase, IBlobIntegrationServic
public async virtual Task DeleteAsync(BlobFileGetByNameIntegrationDto input)
{
- var blobContainer = await BlobContainerRepository.GetByNameAsync(input.ContainerName);
+ var blobContainer = await BlobContainerRepository.GetByNameAsync(BlobManager.GetBlobProvider(), input.ContainerName);
var blob = await FindBlobByNameAsync(blobContainer, input.BlobName)
?? throw new BusinessException(
@@ -90,12 +90,12 @@ public class BlobIntegrationService : BlobAppServiceBase, IBlobIntegrationServic
}
}
- public async virtual Task GetContentAsync(BlobFileGetByNameIntegrationDto input)
+ public async virtual Task DownloadAsync(BlobFileGetByNameIntegrationDto input)
{
try
{
- var blobContainer = await BlobContainerRepository.GetByNameAsync(input.ContainerName);
- return await GetContentByNameAsync(blobContainer, input.BlobName);
+ var blobContainer = await BlobContainerRepository.GetByNameAsync(BlobManager.GetBlobProvider(), input.ContainerName);
+ return await DownloadByNameAsync(blobContainer, input.BlobName);
}
catch (Exception ex)
{
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain.Shared/LINGYUN/Abp/BlobManagement/BlobDownloadEto.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain.Shared/LINGYUN/Abp/BlobManagement/BlobDownloadEto.cs
index 03d5d2d0a..f5fa5f2fb 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain.Shared/LINGYUN/Abp/BlobManagement/BlobDownloadEto.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain.Shared/LINGYUN/Abp/BlobManagement/BlobDownloadEto.cs
@@ -6,6 +6,7 @@ namespace LINGYUN.Abp.BlobManagement;
public class BlobDownloadEto : IMultiTenant
{
public Guid? TenantId { get; set; }
+ public string Provider { get; set; }
public string ContainerName { get; set; }
public string FullName { get; set; }
public BlobDownloadEto()
@@ -13,8 +14,13 @@ public class BlobDownloadEto : IMultiTenant
}
- public BlobDownloadEto(string containerName, string fullName, Guid? tenantId = null)
+ public BlobDownloadEto(
+ string provider,
+ string containerName,
+ string fullName,
+ Guid? tenantId = null)
{
+ Provider = provider;
ContainerName = containerName;
FullName = fullName;
TenantId = tenantId;
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/Blob.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/Blob.cs
index 51258d7be..162938e81 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/Blob.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/Blob.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
+using System.Xml.Linq;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities.Auditing;
@@ -67,6 +68,14 @@ public class Blob : AuditedAggregateRoot, IMultiTenant
this.SetDefaultsForExtraProperties();
}
+ public void MoveTo(Blob parentBlob)
+ {
+ ValidateSubBlob(parentBlob, Name);
+ ParentId = parentBlob.Id;
+ parentBlob.Blobs.Add(this);
+ parentBlob.CalculateSize();
+ }
+
public void SetFullName(string fullName)
{
FullName = Check.NotNullOrWhiteSpace(fullName, nameof(fullName), BlobConsts.MaxFullNameLength);
@@ -99,20 +108,7 @@ public class Blob : AuditedAggregateRoot, IMultiTenant
BlobType type,
long? size = null)
{
- if (Type != BlobType.Folder)
- {
- throw new BusinessException(
- BlobManagementErrorCodes.Blob.NonFolderChildBlob,
- "Sub-files/directories cannot be added to non-directory types!");
- }
-
- if (HasBlob(name))
- {
- throw new BusinessException(
- BlobManagementErrorCodes.Blob.NameAlreadyExists,
- $"There is already a file/directory named {name} in the current directory!")
- .WithData("Name", name);
- }
+ ValidateSubBlob(this, name);
var blob = new Blob(
id,
@@ -183,4 +179,22 @@ public class Blob : AuditedAggregateRoot, IMultiTenant
return blobPath.EnsureEndsWith('/') + blobName.RemovePreFix("/");
}
+
+ public static void ValidateSubBlob(Blob parentBlob, string subBlobName)
+ {
+ if (parentBlob.Type != BlobType.Folder)
+ {
+ throw new BusinessException(
+ BlobManagementErrorCodes.Blob.NonFolderChildBlob,
+ "Sub-files/directories cannot be added to non-directory types!");
+ }
+
+ if (parentBlob.HasBlob(subBlobName))
+ {
+ throw new BusinessException(
+ BlobManagementErrorCodes.Blob.NameAlreadyExists,
+ $"There is already a file/directory named {subBlobName} in the current directory!")
+ .WithData("Name", subBlobName);
+ }
+ }
}
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDataSeeder.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDataSeeder.cs
index e83516959..703e0ac6c 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDataSeeder.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDataSeeder.cs
@@ -41,7 +41,7 @@ public class BlobDataSeeder : IBlobDataSeeder, ITransientDependency
{
Logger.LogInformation("Seeding container {containerName}...", containerName);
- if (await BlobContainerRepository.FindByNameAsync(containerName) == null)
+ if (await BlobManager.FindContainerAsync(containerName) == null)
{
await BlobManager.CreateContainerAsync(containerName);
}
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadIncreaser.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadIncreaser.cs
index bcf2da457..ca074afce 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadIncreaser.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadIncreaser.cs
@@ -37,7 +37,7 @@ public class BlobDownloadIncreaser :
return;
}
- var blobContainer = await _blobContainerRepository.FindByNameAsync(eventData.ContainerName);
+ var blobContainer = await _blobContainerRepository.FindByNameAsync(eventData.Provider, eventData.ContainerName);
if (blobContainer == null)
{
return;
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadKeyCacheItem.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadKeyCacheItem.cs
index 7c001efa9..2f4914c91 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadKeyCacheItem.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobDownloadKeyCacheItem.cs
@@ -16,9 +16,4 @@ public class BlobDownloadKeyCacheItem
BlobId = blobId;
Url = url;
}
-
- public static string CalculateCacheKey(Guid blobId, string blobName)
- {
- return $"{blobId:N}{blobName.RemovePreFix("/")}";
- }
}
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobManager.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobManager.cs
index 68df23011..bf2c0a00d 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobManager.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobManager.cs
@@ -62,11 +62,16 @@ public class BlobManager : DomainService
_settingProvider = settingProvider;
}
- public async virtual Task CreateContainerAsync(string name)
+ public async virtual Task FindContainerAsync(string name)
{
Check.NotNullOrWhiteSpace(name, nameof(name));
- if (await _blobContainerRepository.FindByNameAsync(name) != null)
+ return await _blobContainerRepository.FindByNameAsync(GetBlobProvider(), name);
+ }
+
+ public async virtual Task CreateContainerAsync(string name)
+ {
+ if (await FindContainerAsync(name) != null)
{
throw new BusinessException(
BlobManagementErrorCodes.Container.NameAlreadyExists,
@@ -81,7 +86,7 @@ public class BlobManager : DomainService
await _blobProvider.CreateContainerAsync(blobContainer.Name, GetCancellationToken());
- blobContainer.SetProvider(_blobProvider.Name);
+ blobContainer.SetProvider(GetBlobProvider());
await _blobContainerRepository.InsertAsync(blobContainer);
@@ -153,7 +158,7 @@ public class BlobManager : DomainService
{
await _blobProvider.CreateFolderAsync(blobContainer.Name, blob.FullName, GetCancellationToken());
- blob.SetProvider(_blobProvider.Name);
+ blob.SetProvider(GetBlobProvider());
}
await _blobRepository.InsertAsync(blob);
@@ -227,7 +232,7 @@ public class BlobManager : DomainService
contentType,
GetCancellationToken());
- blob.SetProvider(_blobProvider.Name);
+ blob.SetProvider(GetBlobProvider());
blob.SetFileInfo(contentType, stream.Length);
return blob;
@@ -292,7 +297,7 @@ public class BlobManager : DomainService
}
else
{
- blobContainer = await _blobContainerRepository.GetByNameAsync(containerIdOrName);
+ blobContainer = await _blobContainerRepository.GetByNameAsync(GetBlobProvider(), containerIdOrName);
}
if (parentId.HasValue)
{
@@ -338,9 +343,10 @@ public class BlobManager : DomainService
public async virtual Task GenerateDownloadUrlAsync(
BlobContainer blobContainer,
Blob blob,
- string fallbackUrlPrefix)
+ string fallbackDownloadUrl,
+ bool isAttachmentContent = true)
{
- var cacheKey = BlobDownloadKeyCacheItem.CalculateCacheKey(blob.Id, blob.FullName);
+ var cacheKey = $"{fallbackDownloadUrl.ToMd5()}";
var cacheItem = await _blobDownloadKeyCache.GetAsync(cacheKey);
if (cacheItem == null)
{
@@ -348,16 +354,17 @@ public class BlobManager : DomainService
BlobManagementSettingNames.GenerateDownloadUrlExpirySeconds,
BlobManagementSettingNames.DefaultGenerateDownloadUrlExpirySeconds);
- var downloadUrl = await _blobProvider.GenerateDownloadUrlAsync(
+ var downloadUrl = await _blobProvider.GeneratePresignedUrlAsync(
blobContainer.Name,
blob.FullName,
TimeSpan.FromSeconds(downloadUrlExpirySeconds),
+ isAttachmentContent,
GetCancellationToken());
if (downloadUrl.IsNullOrWhiteSpace())
{
- // 特殊对象存储提供者(FileSystem)无法生成下载链接, 回退指定的请求Url前缀
- downloadUrl = fallbackUrlPrefix.EnsureEndsWith('/') + cacheKey;
+ // 特殊对象存储提供者(FileSystem)无法生成下载链接, 回退指定的请求Url
+ downloadUrl = fallbackDownloadUrl;
}
cacheItem = new BlobDownloadKeyCacheItem(
@@ -403,7 +410,7 @@ public class BlobManager : DomainService
downloadCacheItem.DownloadCount += 1;
await _blobDownloadCache.SetAsync(downloadCacheKey, downloadCacheItem);
- await _distributedEventBus.PublishAsync(new BlobDownloadEto(containerName, blobName, CurrentTenant.Id));
+ await _distributedEventBus.PublishAsync(new BlobDownloadEto(GetBlobProvider(), containerName, blobName, CurrentTenant.Id));
}
return blobStream;
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobTempCleanupService.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobTempCleanupService.cs
index c34de069f..8daa9c837 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobTempCleanupService.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/BlobTempCleanupService.cs
@@ -50,7 +50,7 @@ public class BlobTempCleanupService : ITransientDependency
try
{
- var tempBlobContainer = await BlobContainerRepository.FindByNameAsync("temp");
+ var tempBlobContainer = await BlobManager.FindContainerAsync("temp");
if (tempBlobContainer == null)
{
Logger.LogInformation($"No temp container found.");
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobContainerRepository.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobContainerRepository.cs
index f80d6d228..1dc197e48 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobContainerRepository.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobContainerRepository.cs
@@ -14,6 +14,7 @@ public interface IBlobContainerRepository : IBasicRepository FindByNameAsync(
+ string provider,
string name,
CancellationToken cancellationToken = default);
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobContainerRepositoryExtenssions.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobContainerRepositoryExtenssions.cs
index b5795e01f..e967db5e0 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobContainerRepositoryExtenssions.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobContainerRepositoryExtenssions.cs
@@ -8,10 +8,11 @@ public static class IBlobContainerRepositoryExtenssions
{
public async static Task GetByNameAsync(
this IBlobContainerRepository repository,
+ string provider,
string name,
CancellationToken cancellationToken = default)
{
- return await repository.FindByNameAsync(name, cancellationToken)
+ return await repository.FindByNameAsync(provider, name, cancellationToken)
?? throw new BusinessException(
BlobManagementErrorCodes.Container.NameNotFound,
$"There is no blob container named {name}!")
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobProvider.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobProvider.cs
index 01a012279..61066f83b 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobProvider.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Domain/LINGYUN/Abp/BlobManagement/IBlobProvider.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -22,10 +23,11 @@ public interface IBlobProvider
string blobName,
CancellationToken cancellationToken = default);
- Task GenerateDownloadUrlAsync(
+ Task GeneratePresignedUrlAsync(
string containerName,
string blobName,
TimeSpan expiration,
+ bool isAttachmentContent = true,
CancellationToken cancellationToken = default);
Task CreateFolderAsync(
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.EntityFrameworkCore/LINGYUN/Abp/BlobManagement/EntityFrameworkCore/EfCoreBlobContainerRepository.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.EntityFrameworkCore/LINGYUN/Abp/BlobManagement/EntityFrameworkCore/EfCoreBlobContainerRepository.cs
index 145b304fe..aca9be141 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.EntityFrameworkCore/LINGYUN/Abp/BlobManagement/EntityFrameworkCore/EfCoreBlobContainerRepository.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.EntityFrameworkCore/LINGYUN/Abp/BlobManagement/EntityFrameworkCore/EfCoreBlobContainerRepository.cs
@@ -30,11 +30,12 @@ public class EfCoreBlobContainerRepository : EfCoreRepository FindByNameAsync(
+ string provider,
string name,
CancellationToken cancellationToken = default)
{
return await (await GetQueryableAsync())
- .Where(x => x.Name == name)
+ .Where(x => x.Provider == provider && x.Name == name)
.FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
}
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.FileSystem/LINGYUN/Abp/BlobManagement/FileSystem/FileSystemBlobProvider.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.FileSystem/LINGYUN/Abp/BlobManagement/FileSystem/FileSystemBlobProvider.cs
index 8fcbc8b0f..097e4138b 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.FileSystem/LINGYUN/Abp/BlobManagement/FileSystem/FileSystemBlobProvider.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.FileSystem/LINGYUN/Abp/BlobManagement/FileSystem/FileSystemBlobProvider.cs
@@ -99,10 +99,11 @@ public class FileSystemBlobProvider : IBlobProvider
return Task.FromResult(File.OpenRead(fileName));
}
- public virtual Task GenerateDownloadUrlAsync(
+ public virtual Task GeneratePresignedUrlAsync(
string containerName,
string blobName,
TimeSpan expiration,
+ bool isAttachmentContent = true,
CancellationToken cancellationToken = default)
{
// 本地文件系统无需生成下载链接
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/BlobController.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/BlobController.cs
index 696f7d391..4cff719d0 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/BlobController.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/BlobController.cs
@@ -1,5 +1,6 @@
using LINGYUN.Abp.BlobManagement.Dtos;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Net.Http.Headers;
using System;
using System.Threading.Tasks;
using Volo.Abp;
@@ -50,16 +51,34 @@ public class BlobController : BlobControllerBase, IBlobAppService
return _service.DeleteAsync(id);
}
- [HttpGet("uid/{id}/content")]
- public virtual Task GetContentAsync(Guid id)
+ [HttpGet("download/{id}")]
+ [HttpGet("download/t/{tenantId}/{id}")]
+ public virtual Task DownloadAsync(BlobDownloadByIdInput input)
{
- return _service.GetContentAsync(id);
+ return _service.DownloadAsync(input);
+ }
+
+ [HttpGet("preview/{id}")]
+ [HttpGet("preview/t/{tenantId}/{id}")]
+ public async virtual Task PreviewAsync(BlobDownloadByIdInput input)
+ {
+ var content = await _service.PreviewAsync(input);
+
+ if (!content.FileName.IsNullOrWhiteSpace())
+ {
+ var contentDisposition = new ContentDispositionHeaderValue("inline");
+ contentDisposition.SetHttpFileName(content.FileName);
+ HttpContext.Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
+ }
+
+ return content;
}
- [HttpGet("content")]
- public virtual Task GetContentByNameAsync(BlobDownloadByNameInput input)
+ [HttpGet("download/by-name/{name}")]
+ [HttpGet("download/by-name/t/{tenantId}/{name}")]
+ public virtual Task DownloadByNameAsync(BlobDownloadByNameInput input)
{
- return _service.GetContentByNameAsync(input);
+ return _service.DownloadByNameAsync(input);
}
[HttpGet("{id}")]
@@ -74,17 +93,15 @@ public class BlobController : BlobControllerBase, IBlobAppService
return _service.GetListAsync(input);
}
- [HttpGet("{id}/generate-url")]
+ [HttpGet("generate/download-url/{id}")]
public virtual Task GenerateDownloadUrlAsync(Guid id)
{
return _service.GenerateDownloadUrlAsync(id);
}
- [HttpGet]
- [Route("download/{Key}")]
- [Route("download/t/{TenantId}/{Key}")]
- public virtual Task DownloadAsync(BlobDownloadByKeyInput input)
+ [HttpGet("generate/preview-url/{id}")]
+ public virtual Task GeneratePreviewUrlAsync(Guid id)
{
- return _service.DownloadAsync(input);
+ return _service.GeneratePreviewUrlAsync(id);
}
}
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/Integration/BlobIntegrationController.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/Integration/BlobIntegrationController.cs
index dac00f68f..dc6b4efa0 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/Integration/BlobIntegrationController.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/Integration/BlobIntegrationController.cs
@@ -40,8 +40,8 @@ public class BlobIntegrationController : AbpControllerBase, IBlobIntegrationServ
}
[HttpGet("download")]
- public virtual Task GetContentAsync(BlobFileGetByNameIntegrationDto input)
+ public virtual Task DownloadAsync(BlobFileGetByNameIntegrationDto input)
{
- return _service.GetContentAsync(input);
+ return _service.DownloadAsync(input);
}
}
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/PrivateBlobController.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/PrivateBlobController.cs
index f8ec336a7..20a3b4c1d 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/PrivateBlobController.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/PrivateBlobController.cs
@@ -50,16 +50,16 @@ public class PrivateBlobController : BlobControllerBase, IPrivateBlobAppService
return _service.DeleteAsync(id);
}
- [HttpGet("uid/{id}/content")]
- public virtual Task GetContentAsync(Guid id)
+ [HttpGet("download/{id}")]
+ public virtual Task DownloadAsync(Guid id)
{
- return _service.GetContentAsync(id);
+ return _service.DownloadAsync(id);
}
- [HttpGet("content/{name}")]
- public virtual Task GetContentByNameAsync(string name)
+ [HttpGet("download/by-name/{name}")]
+ public virtual Task DownloadByNameAsync(string name)
{
- return _service.GetContentByNameAsync(name);
+ return _service.DownloadByNameAsync(name);
}
[HttpGet("{id}")]
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/PublicBlobController.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/PublicBlobController.cs
index aca0a128f..ab4610536 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/PublicBlobController.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.HttpApi/LINGYUN/Abp/BlobManagement/PublicBlobController.cs
@@ -22,16 +22,16 @@ public class PublicBlobController : BlobControllerBase, IPublicBlobAppService
_service = service;
}
- [HttpGet("uid/{id}/content")]
- public virtual Task GetContentAsync(Guid id)
+ [HttpGet("download/{id}")]
+ public virtual Task DownloadAsync(Guid id)
{
- return _service.GetContentAsync(id);
+ return _service.DownloadAsync(id);
}
- [HttpGet("content/{name}")]
- public virtual Task GetContentByNameAsync(string name)
+ [HttpGet("download/by-name/{name}")]
+ public virtual Task DownloadByNameAsync(string name)
{
- return _service.GetContentByNameAsync(name);
+ return _service.DownloadByNameAsync(name);
}
[HttpGet("{id}")]
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Minio/LINGYUN/Abp/BlobManagement/Minio/MinioBlobProvider.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Minio/LINGYUN/Abp/BlobManagement/Minio/MinioBlobProvider.cs
index 69414c0c9..a3922136a 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Minio/LINGYUN/Abp/BlobManagement/Minio/MinioBlobProvider.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Minio/LINGYUN/Abp/BlobManagement/Minio/MinioBlobProvider.cs
@@ -4,6 +4,7 @@ using Minio;
using Minio.DataModel.Args;
using Minio.Exceptions;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading;
@@ -108,11 +109,11 @@ public class MinioBlobProvider : IBlobProvider
{
var configuration = GetBlobConfiguration();
- var downloadUrl = await GenerateDownloadUrlAsync(
+ var downloadUrl = await GeneratePresignedUrlAsync(
containerName,
blobName,
TimeSpan.FromSeconds(configuration.PresignedGetExpirySeconds),
- cancellationToken);
+ cancellationToken: cancellationToken);
if (downloadUrl.IsNullOrWhiteSpace())
{
return null;
@@ -123,10 +124,11 @@ public class MinioBlobProvider : IBlobProvider
return await httpClient.GetStreamAsync(downloadUrl, cancellationToken);
}
- public async virtual Task GenerateDownloadUrlAsync(
+ public async virtual Task GeneratePresignedUrlAsync(
string containerName,
string blobName,
TimeSpan expiration,
+ bool isAttachmentContent = true,
CancellationToken cancellationToken = default)
{
var client = GetMinioClient();
@@ -138,11 +140,21 @@ public class MinioBlobProvider : IBlobProvider
return null;
}
- return await client.PresignedGetObjectAsync(
- new PresignedGetObjectArgs()
+ var presignedGetObjectArgs = new PresignedGetObjectArgs()
.WithBucket(bucket)
.WithObject(objectName)
- .WithExpiry(expiration.TotalSeconds.To()));
+ .WithExpiry(expiration.TotalSeconds.To());
+
+ var fileName = Path.GetFileName(blobName);
+ var type = isAttachmentContent ? "attachment" : "inline";
+ var disposition = $"{type}; filename=\"{Uri.EscapeDataString(fileName)}\"; " +
+ $"filename*=UTF-8''{Uri.EscapeDataString(fileName)}";
+ presignedGetObjectArgs.WithHeaders(new Dictionary()
+ {
+ { "response-content-disposition", disposition },
+ });
+
+ return await client.PresignedGetObjectAsync(presignedGetObjectArgs);
}
public virtual Task CreateFolderAsync(
diff --git a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Tencent/LINGYUN/Abp/BlobManagement/Tencent/TencentBlobProvider.cs b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Tencent/LINGYUN/Abp/BlobManagement/Tencent/TencentBlobProvider.cs
index 671525b8d..acdac8f47 100644
--- a/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Tencent/LINGYUN/Abp/BlobManagement/Tencent/TencentBlobProvider.cs
+++ b/aspnet-core/modules/blob-management/LINGYUN.Abp.BlobManagement.Tencent/LINGYUN/Abp/BlobManagement/Tencent/TencentBlobProvider.cs
@@ -6,6 +6,7 @@ using LINGYUN.Abp.BlobStoring.Tencent;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading;
@@ -103,11 +104,11 @@ public class TencentBlobProvider : IBlobProvider
{
var configuration = await GetBlobConfiguration();
- var downloadUrl = await GenerateDownloadUrlAsync(
+ var downloadUrl = await GeneratePresignedUrlAsync(
containerName,
blobName,
TimeSpan.FromSeconds(configuration.PresignedGetExpirySeconds),
- cancellationToken);
+ cancellationToken: cancellationToken);
if (downloadUrl.IsNullOrWhiteSpace())
{
return null;
@@ -118,10 +119,11 @@ public class TencentBlobProvider : IBlobProvider
return await httpClient.GetStreamAsync(downloadUrl, cancellationToken);
}
- public async virtual Task GenerateDownloadUrlAsync(
+ public async virtual Task GeneratePresignedUrlAsync(
string containerName,
string blobName,
TimeSpan expiration,
+ bool isAttachmentContent = true,
CancellationToken cancellationToken = default)
{
var client = await CreateClientAsync();
@@ -147,6 +149,14 @@ public class TencentBlobProvider : IBlobProvider
headers = null, //签名中需要校验的 header
queryParameters = null //签名中需要校验的 URL 中请求参数
};
+ var fileName = Path.GetFileName(blobName);
+ var type = isAttachmentContent ? "attachment" : "inline";
+ var disposition = $"{type}; filename=\"{Uri.EscapeDataString(fileName)}\"; " +
+ $"filename*=UTF-8''{Uri.EscapeDataString(fileName)}";
+ preSignatureStruct.queryParameters = new Dictionary
+ {
+ { "response-content-disposition", disposition },
+ };
return client.GenerateSignURL(preSignatureStruct);
}
diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj b/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
index e04cb7fee..e238f4cc1 100644
--- a/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
+++ b/aspnet-core/services/LY.MicroService.Applications.Single/LY.MicroService.Applications.Single.csproj
@@ -6,6 +6,7 @@
net10.0
enable
LY.MicroService.Applications.Single
+ A47DB958-CC3F-430B-A18A-57AA535BAB49
enable
10.2.0