2025-08-15 16:34:31 +08:00
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using SWS.CAD.Models;
|
|
|
|
|
using SWS.CAD.Models.NoEntity;
|
2025-09-04 18:28:02 +08:00
|
|
|
|
using SWS.Commons;
|
2025-08-15 16:34:31 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Security.Policy;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Web;
|
|
|
|
|
|
|
|
|
|
namespace SWS.CAD.Services
|
|
|
|
|
{
|
|
|
|
|
public class AnnexesService : HttpService
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public AnnexesService() : base()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 查询文件实体
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<annexesfile> GetAnnexesFile(string folderId)
|
|
|
|
|
{
|
|
|
|
|
var res = await this.GetAsync<annexesfile>($"AnnexesApi/GetFileEntity?projectId={GlobalObject.curProject.ProjectId}&folderId={folderId}");
|
|
|
|
|
|
|
|
|
|
if (res.code == 200)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
return res.data;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return null;//ERROR INFO
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 上传本地文件到server
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fullFilePath">完整的路径</param>
|
|
|
|
|
/// <param name="fileName">带后缀</param>
|
|
|
|
|
/// <returns>返回新的一个folder ID</returns>
|
|
|
|
|
public async Task<string> UploadFile(string fullFilePath, string fileName)
|
|
|
|
|
{
|
|
|
|
|
using (var stream = new FileStream(fullFilePath, FileMode.Open, FileAccess.Read))
|
|
|
|
|
{
|
|
|
|
|
var res = await this.PostFileAsync<string>($"AnnexesApi/UploadFile", stream, fileName);
|
|
|
|
|
return res;//new Folder Id
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 下载文件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="url">文件下载地址</param>
|
|
|
|
|
/// <param name="savePath">本地保存路径</param>
|
|
|
|
|
/// <param name="progress">进度报告接口(可选)</param>
|
|
|
|
|
/// <param name="cancellationToken">取消令牌(可选)</param>
|
|
|
|
|
/// <returns>返回空字符串认为是OK的</returns>
|
|
|
|
|
public async Task<string> DownloadFile(
|
|
|
|
|
string savePath, string fileId,
|
|
|
|
|
IProgress<double> progress = null,
|
|
|
|
|
CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var p = Path.GetDirectoryName(savePath);
|
|
|
|
|
if (!Directory.Exists(p))
|
|
|
|
|
Directory.CreateDirectory(p);
|
|
|
|
|
string url = $"AnnexesApi/DownFile?fileId={fileId}";
|
|
|
|
|
// 发送请求并获取响应
|
|
|
|
|
using (var response = await GlobalObject.client.GetAsync(
|
|
|
|
|
url,
|
|
|
|
|
HttpCompletionOption.ResponseHeadersRead,
|
|
|
|
|
cancellationToken))
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (response.StatusCode != HttpStatusCode.OK)
|
|
|
|
|
{
|
|
|
|
|
string errorMsg = $"服务器地址 [{url}] 文件下载失败, 返回HTTP代码:" + response.StatusCode;
|
|
|
|
|
LoggerHelper.Current.Error(errorMsg);
|
|
|
|
|
throw new HttpRequestException(errorMsg);
|
|
|
|
|
}
|
|
|
|
|
response.EnsureSuccessStatusCode(); // 确保响应成功
|
|
|
|
|
var result = await response.Content.ReadAsStringAsync();
|
|
|
|
|
learunHttpRes<object> resultObj = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
resultObj = JsonConvert.DeserializeObject<learunHttpRes<object>>(result);
|
|
|
|
|
}
|
|
|
|
|
catch (JsonException)
|
|
|
|
|
{
|
|
|
|
|
//对下载文件来说,如果正常的话,这里反而是合理的,因为返回的就是stream的东西,不能被解析为learunHttpRes
|
|
|
|
|
await HandleStreamAsync();
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (resultObj.code != 200)
|
|
|
|
|
{
|
|
|
|
|
switch (resultObj.code)
|
|
|
|
|
{
|
|
|
|
|
case 400:
|
|
|
|
|
case 500:
|
|
|
|
|
return resultObj.info.ToString(); //业务错误,不是http本质错误
|
|
|
|
|
default:
|
|
|
|
|
string errorMsg = $"服务器地址 [{url}] Get失败, 返回自定义代码:" + resultObj.code;
|
|
|
|
|
LoggerHelper.Current.Error(errorMsg);
|
|
|
|
|
throw new HttpRequestException(errorMsg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await HandleStreamAsync();
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async Task HandleStreamAsync()
|
|
|
|
|
{
|
|
|
|
|
#region core
|
|
|
|
|
// 获取文件总大小(可能为 null)
|
|
|
|
|
var totalBytes = response.Content.Headers.ContentLength;
|
|
|
|
|
|
|
|
|
|
// 创建文件流
|
|
|
|
|
using (var contentStream = await response.Content.ReadAsStreamAsync())
|
|
|
|
|
using (var fileStream = new FileStream(
|
|
|
|
|
savePath,
|
|
|
|
|
FileMode.Create,
|
|
|
|
|
FileAccess.Write,
|
|
|
|
|
FileShare.None,
|
|
|
|
|
bufferSize: 8192,
|
|
|
|
|
useAsync: true))
|
|
|
|
|
{
|
|
|
|
|
var buffer = new byte[8192];
|
|
|
|
|
var totalBytesRead = 0L;
|
|
|
|
|
var bytesRead = 0;
|
|
|
|
|
|
|
|
|
|
// 分块读取并写入文件
|
|
|
|
|
while ((bytesRead = await contentStream.ReadAsync(
|
|
|
|
|
buffer,
|
|
|
|
|
0,
|
|
|
|
|
buffer.Length,
|
|
|
|
|
cancellationToken)) > 0)
|
|
|
|
|
{
|
|
|
|
|
await fileStream.WriteAsync(
|
|
|
|
|
buffer,
|
|
|
|
|
0,
|
|
|
|
|
bytesRead,
|
|
|
|
|
cancellationToken);
|
|
|
|
|
|
|
|
|
|
totalBytesRead += bytesRead;
|
|
|
|
|
|
|
|
|
|
// 报告进度(如果有总大小)
|
|
|
|
|
if (totalBytes.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var percent = (double)totalBytesRead / totalBytes.Value * 100;
|
|
|
|
|
progress?.Report(percent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (HttpRequestException ex)
|
|
|
|
|
{
|
|
|
|
|
return ex.Message;
|
|
|
|
|
//throw new Exception($"下载请求失败: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
catch (TaskCanceledException ex2)
|
|
|
|
|
{
|
|
|
|
|
return ex2.Message;
|
|
|
|
|
// 取消操作时删除已下载的部分文件
|
|
|
|
|
//if (File.Exists(savePath)) File.Delete(savePath);
|
|
|
|
|
//throw;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex3)
|
|
|
|
|
{
|
|
|
|
|
return ex3.Message;
|
|
|
|
|
//throw new Exception($"下载失败: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|