当前位置: 首页 > news >正文

.net8导出影像图片按现场及天拆分

需求说明

根据日期查询出这个时间段内的现场图片,然后选择现场导出。导出的图片按照一个现场一个文件夹,并且每个现场下按天拆分文件夹。需要兼容文件存储和文件存储的方式。

关键效果图

在这里插入图片描述
在这里插入图片描述

上传Controller关键部分

Controller部分


public class UploadController{private readonly IWebHostEnvironment _env;readonly FileService _fileservice;public UploadController(FileService fileservice,IWebHostEnvironment env){_fileservice = fileservice;_env = env;}/// <summary>/// 现场图片下载/// </summary>/// <returns></returns>[HttpPost]public async Task<Result> SceneImageDownload(JObject obj){var exportData = obj.GetObject<ScenePhoto_Export>("exportData");return await _fileservice.SceneImageDownload(exportData, _env.ContentRootPath);}
}

Servcie部分

public async Task<Result> SceneImageDownload(ScenePhoto_Export exportData, string outputPath = "")
{switch (StorageConfig){case StorageConfig.Cos:  //cos存储case StorageConfig.Oss:  //oss存储case StorageConfig.Obs:  //obs存储 当前年月日字符串var tziprelativePath = $"ExportFiles/{DateTime.Now.Year}/{DateTime.Now.Month}/{DateTime.Now.Day}/"; //相对路径string tzipOutputRoot = Path.Combine(outputPath, tziprelativePath.Replace("/", Path.DirectorySeparatorChar.ToString()));// 确保目录存在if (!Directory.Exists(tzipOutputRoot)){Directory.CreateDirectory(tzipOutputRoot);}string texportFolderName = $"{exportData.Title}";string ttempExportPath = Path.Combine(Path.GetTempPath(), texportFolderName);Directory.CreateDirectory(ttempExportPath);var failList = new List<string>();System.Net.WebClient mywebclient = new System.Net.WebClient();try{foreach (var scene in exportData.SceneList){string sceneFolder = Path.Combine(ttempExportPath, scene.Name);Directory.CreateDirectory(sceneFolder);foreach (var day in scene.DayList){string dayFolder = Path.Combine(sceneFolder, day.ForDate.ToString("yyyy-MM-dd"));Directory.CreateDirectory(dayFolder);foreach (var picGuid in day.PicList){// 查 PicRelation 获取远程文件信息var picData = await _dbContext.Set<PicRelation>().Where(p => p.Pic == picGuid || p.Pic == new Guid(picGuid).ToString()).Select(p => new{p.RemoteUrl,p.Format,}).FirstOrDefaultAsync();if (picData == null || string.IsNullOrEmpty(picData.RemoteUrl)){failList.Add($"未找到云存储图片或 RemoteUrl:{picGuid}");continue;}// 处理文件名,没有 FileName 就用 picGuid + 后缀string extension = string.IsNullOrWhiteSpace(picData.Format) ? ".jpg" : "." + picData.Format.Trim('.');string fileName = picGuid + extension;string destPath = Path.Combine(dayFolder, fileName);try{var bytes = await mywebclient.DownloadDataTaskAsync(picData.RemoteUrl);await System.IO.File.WriteAllBytesAsync(destPath, bytes);}catch (Exception ex){failList.Add($"下载云存储图片失败:{picGuid},错误:{ex.Message}");}}}}if (failList.Any()){string failLogPath = Path.Combine(ttempExportPath, "导出失败.txt");await System.IO.File.WriteAllLinesAsync(failLogPath, failList);}string zipFileName = $"{texportFolderName}.zip";string finalZipPath = Path.Combine(tzipOutputRoot, zipFileName);// 如果已存在,删除旧文件if (System.IO.File.Exists(finalZipPath)){System.IO.File.Delete(finalZipPath);}ZipFile.CreateFromDirectory(ttempExportPath, finalZipPath);var zipPath = $"{_configuration["Service_ApiUrl"]}/{tziprelativePath}{texportFolderName}.zip";return Result.NewSuccess(data: zipPath);}catch (Exception ex){return Result.NewError(message: "导出失败");}finally{if (Directory.Exists(ttempExportPath))Directory.Delete(ttempExportPath, true);}break;case StorageConfig.File: //文件存储var picGuids = exportData.SceneList.SelectMany(t => t.DayList.SelectMany(t => t.PicList)).Select(s => s).ToList();var tpicGuids = picGuids.Select(t => new Guid(t).ToString()).ToList();if (string.IsNullOrEmpty(AppStartingCache.FileStorage_BaseUrl)){bool.TryParse(_configuration["FileWebServer_Db:IsLocal"], out bool islocal);AppStartingCache.FileStorage_IsLocal = islocal;AppStartingCache.FileStorage_BaseUrl = $"http://{_configuration["FileWebServer_Db:ServerHost"]}:{_configuration["FileWebServer_Db:ServerPort"]}";}if (!AppStartingCache.FileStorage_IsLocal)  //远程获取{string fullurl = $"{AppStartingCache.FileStorage_BaseUrl}/file/msupload/SceneImageDownload?";var rst = await HttpClientProxy_Mis.Post2Async<Result<string>>($"{fullurl}", para: new{exportData = exportData});return rst;}else{// 查询图片路径前缀(ServerUseFor = 0)string imageRoot = _dbContext.Set<ImageServerInfo>().Where(s => s.ServerUseFor == ServerUseFor.Pic).Select(s => s.PicRootPath).FirstOrDefault();// 查询压缩包输出根路径(ServerUseFor = 2)string zipOutputRoot = _dbContext.Set<ImageServerInfo>().Where(s => s.ServerUseFor == ServerUseFor.LargeFile).Select(s => s.PicRootPath).FirstOrDefault();var serverId = _dbContext.Set<ImageServerInfo>().Where(s => s.ServerUseFor == ServerUseFor.LargeFile).Select(s => s.Id).FirstOrDefault();if (string.IsNullOrEmpty(imageRoot) || string.IsNullOrEmpty(zipOutputRoot)){return Result.NewError(message: "图片路径前缀或导出目录未配置。");}//得到所有图片的地址及名称var temp = await _dbContext.Set<ImageInfo>().Where(a => picGuids.Contains(a.PicGuid)).Select(s => new{s.PicGuid,s.PicName,s.Format,s.RelativePath}).ToListAsync();if (temp.Count == 0){temp = await _dbContext.Set<ImageInfo>().Where(a => tpicGuids.Contains(a.PicGuid)).Select(s => new{s.PicGuid,s.PicName,s.Format,s.RelativePath}).ToListAsync();}if (temp.Count > 0)//表示有图片 {var imageInfoDict = temp.ToDictionary(x => x.PicGuid, x => x);// 3. 临时目录(系统临时目录)string exportFolderName = $"{exportData.Title}";string tempExportPath = Path.Combine(Path.GetTempPath(), exportFolderName);Directory.CreateDirectory(tempExportPath);try{foreach (var scene in exportData.SceneList){string sceneFolder = Path.Combine(tempExportPath, scene.Name);Directory.CreateDirectory(sceneFolder);foreach (var day in scene.DayList){string dayStr = day.ForDate.ToString("yyyy-MM-dd");string dayFolder = Path.Combine(sceneFolder, dayStr);Directory.CreateDirectory(dayFolder);foreach (var picGuid in day.PicList){if (!imageInfoDict.TryGetValue(picGuid, out var imageInfo))continue; // 没有查到图片信息,跳过string relativePath = imageInfo.RelativePath.Replace("/", Path.DirectorySeparatorChar.ToString());string extension = string.IsNullOrWhiteSpace(imageInfo.Format) ? ".jpg" : "." + imageInfo.Format.Trim('.');string sourcePath = Path.Combine(imageRoot, relativePath);string destPath = Path.Combine(dayFolder, imageInfo.PicName + extension);if (System.IO.File.Exists(sourcePath)){System.IO.File.Copy(sourcePath, destPath, true);}else{Console.WriteLine($"文件不存在:{sourcePath}");}}}}// 4. 生成 zip 文件到 ServerUseFor=1 路径下string zipFileName = $"{exportData.Title}.zip"; 当前年月日字符串var ziprelativePath = $"ExportFiles/{DateTime.Now.Year}/{DateTime.Now.Month}/{DateTime.Now.Day}/"; //相对路径// 构建完整导出路径string finalFolderPath = Path.Combine(zipOutputRoot, ziprelativePath.Replace("/", Path.DirectorySeparatorChar.ToString()));// 确保目录存在if (!Directory.Exists(finalFolderPath)){Directory.CreateDirectory(finalFolderPath);}string finalZipPath = Path.Combine(finalFolderPath, zipFileName);// 如果已存在,删除旧文件if (System.IO.File.Exists(finalZipPath)){System.IO.File.Delete(finalZipPath);}ZipFile.CreateFromDirectory(tempExportPath, finalZipPath);var guid = Guid.NewGuid().ToString("");string zipextension = Path.GetExtension(zipFileName)?.TrimStart('.') ?? "";await _dbContext.Set<ImageInfo>().AddAsync(new ImageInfo{PicName = zipFileName,Format = zipextension,RelativePath = ziprelativePath + exportData.Title + ".zip", // 存储图片相对路径ImageServerId = serverId, // 存储服务器编号PicGuid = guid,CreateOnYMD = DateTime.Now.DateTimeYMD_Int()});await _dbContext.SaveChangesAsync();var serverUrl = await _dbContext.Set<ImageServerInfo>().Where(a => a.Id == serverId).Select(a => a.ServerUrl).FirstOrDefaultAsync();var zipPath = $"{serverUrl}file/msupload/file_misimage?id={guid}";return Result.NewSuccess(data: zipPath);}catch (Exception ex){return Result.NewError(message: "导出失败");}finally{// 清理临时文件夹if (Directory.Exists(tempExportPath))Directory.Delete(tempExportPath, true);}}return Result.NewError(message: "暂无可导出图片");}break;}return Result.NewError(message: "导出失败");
}

文件存储controlelr关键部分

 [HttpGet]public async Task<FileResult> File_Misimage(string id){var rst = await _fileservice.File_Misimage(id);if (!string.IsNullOrEmpty(rst.Format)){rst.Format = rst.Format.Contains('.') ? rst.Format.TrimStart('.') : rst.Format;return File(rst.Pic, MIMEHelper.GetMimeValue(rst.Format), fileDownloadName: $"{rst.FileName}.{rst.Format}");}else{var defaultPic = _defaultimg.DefaultFileStream();return File(defaultPic, MIMEHelper.GetMimeValue("png"), fileDownloadName: "default");}}

文件存储获取文件关键部分

 public async Task<PicByteData> File_Misimage(string id){switch (StorageConfig){case StorageConfig.Cos:case StorageConfig.Oss:case StorageConfig.Obs:var tempid = new Guid(id).ToString();var picData = await _dbContext.Set<PicRelation>().Where(a => a.Pic == tempid).Select(a => new { a.RemoteUrl, a.Format }).FirstOrDefaultAsync();if (picData == null){picData = await _dbContext.Set<PicRelation>().Where(a => a.Pic == id).Select(a => new { a.RemoteUrl, a.Format }).FirstOrDefaultAsync();}if (picData != null){byte[] Bytes = null;using (WebClient mywebclient = new WebClient()){Bytes = mywebclient.DownloadData(picData.RemoteUrl);}return new PicByteData { Pic = Bytes, Format = picData.Format };}break;case StorageConfig.Sqlserver:var guid = new Guid(id);var tmp = await _dbContext.Set<PicStorage>().Where(a => a.Id == guid).Select(a => new { a.Pic, a.Format }).FirstOrDefaultAsync();if (tmp != null){return new PicByteData { Pic = tmp.Pic, Format = tmp.Format };}break;case StorageConfig.File:var tid = new Guid(id).ToString();if (string.IsNullOrEmpty(AppStartingCache.FileStorage_BaseUrl)){bool.TryParse(_configuration["FileWebServer_Db:IsLocal"], out bool islocal);AppStartingCache.FileStorage_IsLocal = islocal;AppStartingCache.FileStorage_BaseUrl = $"http://{_configuration["FileWebServer_Db:ServerHost"]}:{_configuration["FileWebServer_Db:ServerPort"]}";}if (!AppStartingCache.FileStorage_IsLocal)  //远程获取{string fullurl = $"{AppStartingCache.FileStorage_BaseUrl}/file/msupload/file_misimage_byte?id={tid}";var ret = await HttpClientProxy_Mis.GetAsync<PicByteData>(fullurl);return ret;}else{var temp = await (from r in _dbContext.Set<ImageInfo>().Where(a => a.PicGuid == tid)join s in _dbContext.Set<ImageServerInfo>() on r.ImageServerId equals s.Idselect new{s.PicRootPath,r.RelativePath,r.Format,r.PicName}).FirstOrDefaultAsync();if (temp == null){temp = await (from r in _dbContext.Set<ImageInfo>().Where(a => a.PicGuid == id)join s in _dbContext.Set<ImageServerInfo>() on r.ImageServerId equals s.Idselect new{s.PicRootPath,r.RelativePath,r.Format,r.PicName}).FirstOrDefaultAsync();}if (temp != null){var fullpath = temp.PicRootPath + temp.RelativePath;byte[] bytes = null;using (var picstream = System.IO.File.OpenRead(fullpath)){bytes = picstream.ConvertStreamToBytes();picstream.Dispose();}return new PicByteData { Pic = bytes, Format = temp.Format, FileName = temp.PicName };}}break;default:break;}return new PicByteData();}

模型部分

  public class PicByteData{public byte[] Pic { get; set; }public string Format { get; set; }/// <summary>/// 文件名称/// </summary>public string FileName { get; set; }}
http://www.xdnf.cn/news/1075123.html

相关文章:

  • 调试W5500(作为服务器)
  • macos 使用 vllm 启动模型
  • 【微服务】.Net中使用Consul实现服务高可用
  • 51c大模型~合集144
  • 2025年光学工程、精密仪器与光电子技术国际会议(OEPIOT 2025)
  • 物联网基础
  • Git 常用命令、常用错误的总结
  • 2 大语言模型基础-2.2 生成式预训练语言模型GPT-2.2.2 有监督下游任务微调-Instruct-GPT强化学习奖励模型的结构改造与维度转换解析
  • [论文阅读] Neural Architecture Search: Insights from 1000 Papers
  • 超表面重构卡塞格林望远镜 | 从传统架构到新型光学系统
  • 最大矩形最大正方形-力扣
  • 优雅草蜻蜓HR人才招聘系统v2.0.9上线概要 -优雅草新产品上线
  • 飞算JavaAI 2.0.0深度测评:自然语言编程如何重构开发生产力?
  • 键盘第一下无反应
  • 04密码加密
  • C#程序调用cmd执行命令
  • 卡片跳转到应用页面(router事件)
  • 生成式人工智能实战 | 变分自编码器(Variational Auto-Encoder, VAE)
  • 基于STM32温湿度检测—串口显示
  • HTML5 实现的圣诞主题网站源码,使用了 HTML5 和 CSS3 技术,界面美观、节日氛围浓厚。
  • k8s pod深度解析
  • k8s创建定时的 Python 任务(CronJob)
  • 【c/c++1】数据类型/指针/结构体,static/extern/makefile/文件
  • 机器学习9——决策树
  • 新生代潜力股刘小北:演艺路上的璀璨新星
  • ROS常用的路径规划算法介绍
  • 面试复盘6.0
  • Java面试宝典:基础四
  • SpringSecurity6-oauth2-三方gitee授权-授权码模式
  • 详解快速排序