chore: initial commit
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user