Files
16-Xikai-MesProjectNew/Interface_WebAPI/SlMesDbIterface/WebAPI/Controller/CheckImageController.cs
2026-05-29 09:34:04 +08:00

271 lines
9.9 KiB
C#

using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.RegularExpressions;
using System.Web.Http;
using DataLinkMesWork2;
namespace WebApi
{
[RoutePrefix("api/checkimage")]
public class CheckImageController : ApiController
{
private readonly string _defaultRoot = @"D:\\XDCheckImages";
public class ImageUploadRequest
{
public string ProductCode { get; set; }
public string Remark { get; set; }
public string ImageBase64 { get; set; }
public string FileExt { get; set; }
}
public class ImageDownloadRequest
{
public string Path { get; set; }
}
private string GetRootPath()
{
string root = null;
try
{
root = ConfigurationManager.AppSettings["XD_CheckImageRootPath"];
}
catch
{
}
if (string.IsNullOrWhiteSpace(root))
{
root = _defaultRoot;
}
return root;
}
private string SanitizeForPath(string input)
{
if (string.IsNullOrEmpty(input)) return string.Empty;
char[] invalid = Path.GetInvalidFileNameChars();
var value = input.Trim();
foreach (var c in invalid)
{
value = value.Replace(c.ToString(), string.Empty);
}
value = value.Replace("/", string.Empty).Replace("\\", string.Empty);
return value;
}
private string GetExtensionFromRequest(ImageUploadRequest request)
{
string ext = ".jpg";
if (request == null) return ext;
if (!string.IsNullOrWhiteSpace(request.FileExt))
{
ext = request.FileExt.Trim();
if (!ext.StartsWith("."))
{
ext = "." + ext;
}
return ext;
}
if (!string.IsNullOrWhiteSpace(request.ImageBase64) &&
request.ImageBase64.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
{
try
{
var match = Regex.Match(request.ImageBase64, "^data:(?<mime>[^;]+);base64,", RegexOptions.IgnoreCase);
if (match.Success)
{
var mime = match.Groups["mime"].Value.ToLowerInvariant();
if (mime == "image/png") return ".png";
if (mime == "image/gif") return ".gif";
if (mime == "image/bmp") return ".bmp";
if (mime == "image/webp") return ".webp";
if (mime == "image/tiff" || mime == "image/tif") return ".tif";
if (mime == "image/jpeg" || mime == "image/jpg") return ".jpg";
}
}
catch
{
}
}
return ext;
}
private string GetContentType(string fileName)
{
var extension = Path.GetExtension(fileName).ToLowerInvariant();
if (extension == ".bmp") return "image/bmp";
if (extension == ".jpg" || extension == ".jpeg") return "image/jpeg";
if (extension == ".png") return "image/png";
if (extension == ".gif") return "image/gif";
if (extension == ".tiff" || extension == ".tif") return "image/tiff";
if (extension == ".webp") return "image/webp";
return "application/octet-stream";
}
private bool IsPathSafe(string fullPath)
{
try
{
var basePath = Path.GetFullPath(GetRootPath());
var requestedPath = Path.GetFullPath(fullPath);
return requestedPath.StartsWith(basePath, StringComparison.OrdinalIgnoreCase);
}
catch
{
return false;
}
}
[HttpPost]
[Route("upload")]
public IHttpActionResult Upload([FromBody] ImageUploadRequest request)
{
try
{
if (request == null ||
string.IsNullOrWhiteSpace(request.ProductCode) ||
string.IsNullOrWhiteSpace(request.Remark) ||
string.IsNullOrWhiteSpace(request.ImageBase64))
{
return Ok(new { success = false, message = "产品编号、备注和图片不能为空" });
}
string productCode = SanitizeForPath(request.ProductCode);
string remark = SanitizeForPath(request.Remark);
if (string.IsNullOrEmpty(productCode))
{
return Ok(new { success = false, message = "产品编号无效" });
}
string ext = GetExtensionFromRequest(request);
string base64 = request.ImageBase64.Trim();
int commaIndex = base64.IndexOf(',');
if (base64.StartsWith("data:", StringComparison.OrdinalIgnoreCase) && commaIndex > 0)
{
base64 = base64.Substring(commaIndex + 1);
}
byte[] bytes;
try
{
bytes = Convert.FromBase64String(base64);
}
catch
{
return Ok(new { success = false, message = "图片数据格式错误" });
}
var now = DateTime.Now;
string datePart = now.ToString("yyyyMMdd");
string timePart = now.ToString("HHmmss");
string fileName = string.Format("{0}-{1}-{2}{3}", timePart, productCode, remark, ext);
string relativePath = string.Format("/{0}/{1}", datePart, fileName);
string root = GetRootPath();
string directory = Path.Combine(root, datePart);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
string fullPath = Path.Combine(directory, fileName);
if (!IsPathSafe(fullPath))
{
return Ok(new { success = false, message = "目标路径不安全" });
}
File.WriteAllBytes(fullPath, bytes);
string errorMessage;
var sqlParameters = new SqlParameter[4];
sqlParameters[0] = new SqlParameter("@产品编号", SqlDbType.NVarChar, 500) { Value = (object)request.ProductCode ?? DBNull.Value };
sqlParameters[1] = new SqlParameter("@备注", SqlDbType.NVarChar, 500) { Value = (object)request.Remark ?? DBNull.Value };
sqlParameters[2] = new SqlParameter("@图片路径", SqlDbType.NVarChar, 500) { Value = (object)relativePath ?? DBNull.Value };
sqlParameters[3] = new SqlParameter("@图片名称", SqlDbType.NVarChar, 500) { Value = (object)fileName ?? DBNull.Value };
bool dbOk = DataAccess2.ExecuteStoredProcedure("XD_检测图片上传_增加", ref sqlParameters, out errorMessage);
if (!dbOk)
{
return Ok(new { success = false, message = "图片已保存,但写入数据库失败:" + errorMessage });
}
return Ok(new
{
success = true,
message = "上传成功",
data = new
{
= request.ProductCode,
= request.Remark,
= relativePath,
= fileName
}
});
}
catch (Exception ex)
{
return Ok(new { success = false, message = "服务器错误:" + ex.Message });
}
}
[HttpPost]
[Route("download")]
public IHttpActionResult Download([FromBody] ImageDownloadRequest request)
{
try
{
if (request == null || string.IsNullOrWhiteSpace(request.Path))
{
return Ok(new { success = false, message = "文件路径不能为空" });
}
string root = GetRootPath();
string relative = request.Path.Replace("\\", "/").Trim();
if (relative.StartsWith("/"))
{
relative = relative.Substring(1);
}
string fullPath = Path.Combine(root, relative.Replace('/', Path.DirectorySeparatorChar));
if (!IsPathSafe(fullPath) || !File.Exists(fullPath))
{
return Ok(new { success = false, message = "文件不存在" });
}
var fileInfo = new FileInfo(fullPath);
var contentType = GetContentType(fileInfo.Name);
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
{
FileName = fileInfo.Name
};
return ResponseMessage(response);
}
catch (Exception ex)
{
return Ok(new { success = false, message = "下载文件失败:" + ex.Message });
}
}
}
}