@@ -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>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()
|
||||||
|
|||||||
@@ -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"];
|
||||||
|
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
Reference in New Issue
Block a user