😎优化文件存储数据库相关代码
This commit is contained in:
parent
e241ce5c3b
commit
7ae8e5e00f
@ -6,7 +6,7 @@
|
||||
"MaxSize": 51200, // 文件最大限制KB:1024*50
|
||||
"ContentType": [ "image/jpg", "image/png", "image/jpeg", "image/gif", "image/bmp", "text/plain", "text/xml", "application/pdf", "application/msword", "application/vnd.ms-excel", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "video/mp4", "application/wps-office.docx", "application/wps-office.xlsx", "application/wps-office.pptx", "application/vnd.android.package-archive", "application/octet-stream" ],
|
||||
"EnableMd5": false, // 启用文件MDF5验证-防止重复上传
|
||||
"EnableSaveFileToDb": false //把文件保存到数据库的表里,个别小的应用如果要集群部署时,这种方式比较方便。
|
||||
"EnableSaveDb": false // 启用文件存储到数据库
|
||||
},
|
||||
"OSSProvider": {
|
||||
"Enabled": false,
|
||||
|
||||
@ -27,10 +27,10 @@
|
||||
<PackageReference Include="AspectCore.Extensions.Reflection" Version="2.4.0" />
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.1" Aliases="BouncyCastleV2" />
|
||||
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.0.6" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.88" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.88" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.88" />
|
||||
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="9.0.7" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.89" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.89" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.89" />
|
||||
<PackageReference Include="Hardware.Info" Version="101.0.1.1" />
|
||||
<PackageReference Include="Hashids.net" Version="1.7.0" />
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
|
||||
@ -35,10 +35,9 @@ public sealed class UploadOptions : IConfigurableOptions
|
||||
public bool EnableMd5 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 把文件保存到数据库的表里
|
||||
/// 启用文件存储到数据库
|
||||
/// </summary>
|
||||
|
||||
public bool EnableSaveFileToDb { get; set; }
|
||||
public bool EnableSaveDb { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Furion.DependencyInjection;
|
||||
|
||||
namespace Admin.NET.Core.Service;
|
||||
|
||||
public class DbFileProvider : ICustomFileProvider, ITransient
|
||||
@ -24,7 +22,8 @@ public class DbFileProvider : ICustomFileProvider, ITransient
|
||||
}
|
||||
|
||||
public async Task<string> DownloadFileBase64Async(SysFile sysFile)
|
||||
{// 考虑可能会曾经配置成保存到本地文件
|
||||
{
|
||||
// 若先前配置成保存到本地文件
|
||||
if (string.IsNullOrEmpty(sysFile.Provider) || sysFile.Provider == "Local")
|
||||
{
|
||||
var provider = App.GetService<DefaultFileProvider>();
|
||||
@ -45,7 +44,7 @@ public class DbFileProvider : ICustomFileProvider, ITransient
|
||||
|
||||
public async Task<FileStreamResult> GetFileStreamResultAsync(SysFile sysFile, string fileName)
|
||||
{
|
||||
// 考虑可能会曾经配置成保存到本地文件
|
||||
// 若先前配置成保存到本地文件
|
||||
if (string.IsNullOrEmpty(sysFile.Provider) || sysFile.Provider == "Local")
|
||||
{
|
||||
var provider = App.GetService<DefaultFileProvider>();
|
||||
|
||||
@ -131,27 +131,19 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在upload路径下载文件 🔖
|
||||
/// 根据文件Id和MD5下载(与db存储模式路径对应) 🔖
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="fileMd5"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// 这个接口定义在 /upload/downloadfile与DbFileProvider返回的路径要对应得上,
|
||||
/// 之所以定义在这里,有利于使用反向代理指入我们的upload文件夹时不用修改文件的下载路径。
|
||||
/// 比如我们的前端就把他自己的upload转发到了我们后端的upload路径,所以这种情况下,我们用db来保存文件时,就不用修改下载文件的方式
|
||||
/// </remarks>
|
||||
[Route("/upload/downloadfile")]
|
||||
[AllowAnonymous]
|
||||
[HttpGet]
|
||||
[DisplayName("在upload路径")]
|
||||
public async Task<IActionResult> DownloadFile2([FromQuery]long id, [FromQuery] string fileMd5, [FromQuery] string fileName)
|
||||
[HttpGet("/upload/downloadfile")]
|
||||
[DisplayName("根据文件Id和MD5下载")]
|
||||
public async Task<IActionResult> DownloadFile2([FromQuery] long id, [FromQuery] string fileMd5)
|
||||
{
|
||||
var file = await GetFile(id);
|
||||
if (file.FileMd5 != null && file.FileMd5 != fileMd5)
|
||||
throw Oops.Bah("文件校验信息不符");
|
||||
fileName = HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8"));
|
||||
if (file.FileMd5 != null && file.FileMd5 != fileMd5) throw Oops.Oh("文件校验信息不符");
|
||||
|
||||
var fileName = HttpUtility.UrlEncode(file.FileName, Encoding.GetEncoding("UTF-8"));
|
||||
return await GetFileStreamResult(file, fileName);
|
||||
}
|
||||
|
||||
|
||||
@ -575,9 +575,7 @@ public class SysTenantService : IDynamicApiController, ITransient
|
||||
|
||||
if (tenantId < 1) tenantId = long.Parse(App.User?.FindFirst(ClaimConst.TenantId)?.Value ?? "0");
|
||||
if (tenantId < 1) tenantId = SqlSugarConst.DefaultTenantId;
|
||||
var tenant = await _sysTenantRep.GetFirstAsync(u => u.Id == tenantId);
|
||||
if (tenant == null)
|
||||
throw Oops.Bah($"租户信息不存在:{tenantId}");
|
||||
var tenant = await _sysTenantRep.GetFirstAsync(u => u.Id == tenantId) ?? throw Oops.Oh($"租户信息不存在:{tenantId}");
|
||||
|
||||
// 若租户系统标题为空,则获取默认租户系统信息(兼容已有未配置的租户)
|
||||
if (string.IsNullOrWhiteSpace(tenant.Title))
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "admin.net.pro",
|
||||
"type": "module",
|
||||
"version": "2.4.33",
|
||||
"lastBuildTime": "2025.06.19",
|
||||
"lastBuildTime": "2025.06.20",
|
||||
"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",
|
||||
"author": "zuohuaijun",
|
||||
"license": "MIT",
|
||||
@ -24,7 +24,7 @@
|
||||
"@vue-office/docx": "^1.6.2",
|
||||
"@vue-office/excel": "^1.7.14",
|
||||
"@vue-office/pdf": "^2.0.9",
|
||||
"@vueuse/core": "^13.3.0",
|
||||
"@vueuse/core": "^13.4.0",
|
||||
"@vxe-ui/plugin-export-xlsx": "^4.2.2",
|
||||
"@vxe-ui/plugin-render-element": "^4.0.11",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
@ -83,8 +83,8 @@
|
||||
"vue-router": "^4.5.1",
|
||||
"vue-signature-pad": "^3.0.2",
|
||||
"vue3-tree-org": "^4.2.2",
|
||||
"vxe-pc-ui": "^4.6.26",
|
||||
"vxe-table": "^4.13.43",
|
||||
"vxe-pc-ui": "^4.6.27",
|
||||
"vxe-table": "^4.13.44",
|
||||
"xe-utils": "^3.7.5",
|
||||
"xlsx-js-style": "^1.2.0"
|
||||
},
|
||||
@ -108,7 +108,7 @@
|
||||
"prettier": "^3.5.3",
|
||||
"rollup-plugin-visualizer": "^6.0.3",
|
||||
"sass": "^1.89.2",
|
||||
"terser": "^5.43.0",
|
||||
"terser": "^5.43.1",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-cdn-import": "^1.0.1",
|
||||
|
||||
@ -738,6 +738,59 @@ export const SysFileApiAxiosParamCreator = function (configuration?: Configurati
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = localVarFormParams;
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 根据文件Id和MD5下载(与db存储模式路径对应) 🔖
|
||||
* @param {number} [id]
|
||||
* @param {string} [fileMd5]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
uploadDownloadfileGet: async (id?: number, fileMd5?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/upload/downloadfile`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
// authentication Bearer required
|
||||
// http bearer authentication required
|
||||
if (configuration && configuration.accessToken) {
|
||||
const accessToken = typeof configuration.accessToken === 'function'
|
||||
? await configuration.accessToken()
|
||||
: await configuration.accessToken;
|
||||
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
|
||||
}
|
||||
|
||||
if (id !== undefined) {
|
||||
localVarQueryParameter['id'] = id;
|
||||
}
|
||||
|
||||
if (fileMd5 !== undefined) {
|
||||
localVarQueryParameter['fileMd5'] = fileMd5;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(localVarUrlObj.search);
|
||||
for (const key in localVarQueryParameter) {
|
||||
query.set(key, localVarQueryParameter[key]);
|
||||
}
|
||||
for (const key in options.params) {
|
||||
query.set(key, options.params[key]);
|
||||
}
|
||||
localVarUrlObj.search = (new URLSearchParams(query)).toString();
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
|
||||
options: localVarRequestOptions,
|
||||
@ -952,6 +1005,21 @@ export const SysFileApiFp = function(configuration?: Configuration) {
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 根据文件Id和MD5下载(与db存储模式路径对应) 🔖
|
||||
* @param {number} [id]
|
||||
* @param {string} [fileMd5]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async uploadDownloadfileGet(id?: number, fileMd5?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultIActionResult>>> {
|
||||
const localVarAxiosArgs = await SysFileApiAxiosParamCreator(configuration).uploadDownloadfileGet(id, fileMd5, options);
|
||||
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
|
||||
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
|
||||
return axios.request(axiosRequestArgs);
|
||||
};
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -1105,6 +1173,17 @@ export const SysFileApiFactory = function (configuration?: Configuration, basePa
|
||||
async apiSysFileUploadSignaturePostForm(file?: Blob, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultSysFile>> {
|
||||
return SysFileApiFp(configuration).apiSysFileUploadSignaturePostForm(file, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary 根据文件Id和MD5下载(与db存储模式路径对应) 🔖
|
||||
* @param {number} [id]
|
||||
* @param {string} [fileMd5]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async uploadDownloadfileGet(id?: number, fileMd5?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultIActionResult>> {
|
||||
return SysFileApiFp(configuration).uploadDownloadfileGet(id, fileMd5, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -1273,4 +1352,16 @@ export class SysFileApi extends BaseAPI {
|
||||
public async apiSysFileUploadSignaturePostForm(file?: Blob, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultSysFile>> {
|
||||
return SysFileApiFp(this.configuration).apiSysFileUploadSignaturePostForm(file, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @summary 根据文件Id和MD5下载(与db存储模式路径对应) 🔖
|
||||
* @param {number} [id]
|
||||
* @param {string} [fileMd5]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof SysFileApi
|
||||
*/
|
||||
public async uploadDownloadfileGet(id?: number, fileMd5?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultIActionResult>> {
|
||||
return SysFileApiFp(this.configuration).uploadDownloadfileGet(id, fileMd5, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user