附件
build / build-push (push) Successful in 1m21s

This commit is contained in:
wanghu
2026-09-09 16:27:17 +08:00
parent 4211b72041
commit 0efde94a74
4 changed files with 50 additions and 19 deletions
+10 -3
View File
@@ -214,9 +214,15 @@ namespace YhCore.Service.Impl
if (string.IsNullOrEmpty(fileUrl)) if (string.IsNullOrEmpty(fileUrl))
return ""; return "";
// 相对路径如 /upload/docprint/20260101/{guid}.jpg → Config.FilePath + 子路径 // 新数据:fileurl 以 FILE_PATH 开头(如 /data/upload/docprint/20260101/{guid}.jpg)→ 剥前缀映射回 FILE_PATH。
// 注意必须用未 TrimStart 的原始 fileUrl 比较(FILE_PATH 本身以 / 开头)
string fp = Config.FilePath;
if (!string.IsNullOrEmpty(fp) && fileUrl.StartsWith(fp, StringComparison.OrdinalIgnoreCase))
return Path.Combine(fp, fileUrl.Substring(fp.Length).TrimStart('/').Replace('/', Path.DirectorySeparatorChar));
// 旧数据:相对路径如 /upload/docprint/20260101/{guid}.jpg(不含 FILE_PATH 前缀)→ StorageRoot + 子路径
var relative = fileUrl.TrimStart('/'); var relative = fileUrl.TrimStart('/');
string prefix = Config.FilePath; const string prefix = "upload/";
if (relative.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) if (relative.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
relative = relative.Substring(prefix.Length); relative = relative.Substring(prefix.Length);
@@ -229,7 +235,8 @@ namespace YhCore.Service.Impl
if (!string.IsNullOrEmpty(Config.FilePath)) if (!string.IsNullOrEmpty(Config.FilePath))
return Config.FilePath; return Config.FilePath;
return Path.Combine(AppContext.BaseDirectory,Config.FilePath); // 此分支仅在 FILE_PATH 未配置时执行(此时 Config.FilePath 为 null,不可再参与拼接)
return Path.Combine(AppContext.BaseDirectory, "upload");
} }
} }
} }
@@ -235,42 +235,58 @@ namespace YhCore.WebApi.Controllers.Api.Common
/// <summary> /// <summary>
/// 公用附件上传(旧 FileUpload,[NoAuth])。 /// 公用附件上传(旧 FileUpload,[NoAuth])。
/// chunk 参数 → 分片保存返回 {code:1,type:"chunk",msg};fileName 参数 → 合并分片;否则单文件上传。 /// 分片(chunk/chunkIndex + totalChunks&gt;1)→ 分片保存返回 {code:1,type:"chunk",msg};
/// 只带 fileName 不带文件 → 合并分片;带文件 → 单文件直传
/// (前端单文件直传也会带 guid/chunkIndex=0/totalChunks=0/fileName,不得误入合并分支)。
/// guid/chunk/fileName 兼容 query 与 form 两种形态(旧版读 Query)。
/// 落库 Common_UpFiles(TopicType=AppCode),返回 {fileurl,host,fileid,name,type}。 /// 落库 Common_UpFiles(TopicType=AppCode),返回 {fileurl,host,fileid,name,type}。
/// </summary> /// </summary>
[HttpPost("FileUpload")] [HttpPost("FileUpload")]
public async Task<object> Upload() public async Task<object> Upload()
{ {
string apptype = "docprint"; // 旧 WebHelper.AppType 固定 docprint string apptype = "docprint"; // 旧 WebHelper.AppType 固定 docprint
string guid = Request.Form["guid"]; string guid = FormOrQuery("guid");
string chunk = Request.Form["chunk"]; string chunk = FormOrQuery("chunk"); // 旧契约分片序号
string fileName = Request.Form["fileName"]; string chunkIndex = FormOrQuery("chunkIndex"); // 前端现用分片序号
string totalChunks = FormOrQuery("totalChunks");
string fileName = FormOrQuery("fileName");
if (!string.IsNullOrEmpty(chunk)) var file = Request.Form.Files.FirstOrDefault(f => f.Name == "file") ?? Request.Form.Files.FirstOrDefault();
bool multiChunk = int.TryParse(totalChunks, out var total) && total > 1;
bool isChunkReq = file != null
&& (!string.IsNullOrEmpty(chunk) || (!string.IsNullOrEmpty(chunkIndex) && multiChunk));
if (isChunkReq)
{ {
var chunkFile = Request.Form.Files.FirstOrDefault(f => f.Name == "file") ?? Request.Form.Files.FirstOrDefault(); await _file.SaveChunkAsync(guid, string.IsNullOrEmpty(chunk) ? chunkIndex : chunk, file);
await _file.SaveChunkAsync(guid, chunk, chunkFile);
return new { code = 1, type = "chunk", msg = "分片上传成功!" }; return new { code = 1, type = "chunk", msg = "分片上传成功!" };
} }
FileObj url; FileObj url;
string errMsg = "上传失败!"; if (!string.IsNullOrEmpty(fileName) && file == null)
if (string.IsNullOrEmpty(fileName))
{ {
url = await _file.SaveFileAsync(apptype, Request.Form.Files.FirstOrDefault()); url = await _file.MergeSaveAsync(apptype, guid, fileName); // 合并分片
} }
else else
{ {
url = await _file.MergeSaveAsync(apptype, guid, fileName); url = await _file.SaveFileAsync(apptype, file); // 单文件直传
} }
if (url == null) if (url == null)
throw new DException(errMsg); throw new DException("上传失败!");
// 旧 WebHelper.AppCode == "1102" ? "1002" : AppCode → docprint 固定 1003 // 旧 WebHelper.AppCode == "1102" ? "1002" : AppCode → docprint 固定 1003
int serid = await _file.SaveEnclosureAsync(url, DocPrintConstants.AppCode.ToString()); int serid = await _file.SaveEnclosureAsync(url, DocPrintConstants.AppCode.ToString());
return new { fileurl = url.fileurl, host = url.host, fileid = serid, name = url.filename, type = url.filetype }; return new { fileurl = url.fileurl, host = url.host, fileid = serid, name = url.filename, type = url.filetype };
} }
/// <summary>取表单/URL 参数(旧版读 Request["x"] 同时覆盖 Query+Form)。</summary>
private string FormOrQuery(string name)
{
var v = Request.Form[name].ToString();
if (!string.IsNullOrEmpty(v)) return v;
return Request.Query[name].ToString();
}
/// <summary>公用图片上传(旧 FileUploadImage,[NoAuth];多图,返回数组)。</summary> /// <summary>公用图片上传(旧 FileUploadImage,[NoAuth];多图,返回数组)。</summary>
[HttpPost("FileUploadImage")] [HttpPost("FileUploadImage")]
public async Task<object> UploadImg() public async Task<object> UploadImg()
+11 -3
View File
@@ -175,9 +175,17 @@ namespace YhCore.WebApi
.Bind(Configuration.GetSection("Swagger")); .Bind(Configuration.GetSection("Swagger"));
services.AddOptions<YhCore.Common.Config.FileConfig>() services.AddOptions<YhCore.Common.Config.FileConfig>()
.Bind(Configuration); .Bind(Configuration);
// 静态门面(对齐 Java Config):文件路径由配置注入 // 静态门面(对齐 Java Config):文件路径由配置注入。
YhCore.Common.Config.Config.FilePath = Configuration["FILE_PATH"]; // FILE_PATH 必须以 / 结尾(旧约定:FileService 多处 FilePath + "{appType}/..." 直接拼接,缺斜杠会拼出坏路径);
YhCore.Common.Config.Config.FileWebPath = Configuration["FILE_WEB_PATH"]; // FILE_WEB_PATH 不带尾 /(拼接目标 fileurl 均以 / 开头,带尾斜杠会产生 //)
var configFilePath = Configuration["FILE_PATH"];
YhCore.Common.Config.Config.FilePath = string.IsNullOrEmpty(configFilePath)
? configFilePath
: configFilePath.TrimEnd('/').Replace('\\', '/') + "/";
var configFileWebPath = Configuration["FILE_WEB_PATH"];
YhCore.Common.Config.Config.FileWebPath = string.IsNullOrEmpty(configFileWebPath)
? configFileWebPath
: configFileWebPath.TrimEnd('/');
// 审批单 PDF:wkhtmltopdf 可执行文件路径(空则用 PATH) // 审批单 PDF:wkhtmltopdf 可执行文件路径(空则用 PATH)
YhCore.Common.Config.Config.WkHtmlToPdfPath = Configuration["wkhtmltopdf_path"]; YhCore.Common.Config.Config.WkHtmlToPdfPath = Configuration["wkhtmltopdf_path"];
+1 -1
View File
@@ -10,7 +10,7 @@
"Redis": { "Redis": {
"ConnectionString": "localhost:6379,defaultDatabase=0" "ConnectionString": "localhost:6379,defaultDatabase=0"
}, },
"FILE_PATH": "", "FILE_PATH": "/data/upload/",
"FILE_WEB_PATH": "", "FILE_WEB_PATH": "",
"wkhtmltopdf_path": "", "wkhtmltopdf_path": "",
"yh": { "yh": {