feat: enhance error handling and backup functionality in ShellOptimizer
This commit is contained in:
parent
a0c89cac52
commit
80051f3759
@ -288,8 +288,26 @@ namespace RevitHttpControl.Controllers
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
if (ex.Message.Contains(ErrorMessages.NO_DOCUMENT_OPEN_MSG))
|
||||
{
|
||||
return this.CreateErrorResponse(
|
||||
ErrorCodes.NO_DOCUMENT_OPEN,
|
||||
ex.Message,
|
||||
HttpStatusCode.BadRequest
|
||||
);
|
||||
}
|
||||
|
||||
if (ex.Message.Contains("创建备份失败"))
|
||||
{
|
||||
return this.CreateErrorResponse(
|
||||
ErrorCodes.FILE_WRITE_PERMISSION_DENIED,
|
||||
ex.Message,
|
||||
HttpStatusCode.Forbidden
|
||||
);
|
||||
}
|
||||
|
||||
return this.CreateErrorResponse(
|
||||
ErrorCodes.NO_DOCUMENT_OPEN,
|
||||
ErrorCodes.REVIT_COMMAND_FAILED,
|
||||
ex.Message,
|
||||
HttpStatusCode.BadRequest
|
||||
);
|
||||
|
||||
@ -274,10 +274,22 @@ namespace RevitHttpControl.Services
|
||||
if (worksetId != WorksetId.InvalidWorksetId)
|
||||
{
|
||||
var doc = element.Document;
|
||||
var worksetTable = doc.GetWorksetTable();
|
||||
var workset = worksetTable.GetWorkset(worksetId);
|
||||
if (workset.IsOpen && workset.Owner != doc.Application.Username)
|
||||
return false;
|
||||
// 仅对工作共享文档执行“他人占用”校验,避免本地/样例文件误判。
|
||||
if (doc.IsWorkshared)
|
||||
{
|
||||
var worksetTable = doc.GetWorksetTable();
|
||||
var workset = worksetTable.GetWorkset(worksetId);
|
||||
var owner = workset?.Owner;
|
||||
var currentUser = doc.Application?.Username;
|
||||
|
||||
if (workset != null &&
|
||||
workset.IsOpen &&
|
||||
!string.IsNullOrWhiteSpace(owner) &&
|
||||
!string.Equals(owner, currentUser, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有依赖关系(如主体构件)
|
||||
@ -341,18 +353,38 @@ namespace RevitHttpControl.Services
|
||||
throw new InvalidOperationException("文档必须先保存才能创建备份");
|
||||
}
|
||||
|
||||
var directory = Path.GetDirectoryName(originalPath);
|
||||
var fileName = Path.GetFileNameWithoutExtension(originalPath);
|
||||
var extension = Path.GetExtension(originalPath);
|
||||
var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
||||
|
||||
var backupFileName = $"{fileName}_backup_{timestamp}{extension}";
|
||||
var backupPath = Path.Combine(directory, backupFileName);
|
||||
|
||||
// 复制文件
|
||||
File.Copy(originalPath, backupPath, false);
|
||||
|
||||
return backupPath;
|
||||
// 先尝试写入原目录;若无权限则回退到用户本地目录。
|
||||
var sourceDirectory = Path.GetDirectoryName(originalPath);
|
||||
if (!string.IsNullOrWhiteSpace(sourceDirectory))
|
||||
{
|
||||
var backupPathInSource = Path.Combine(sourceDirectory, backupFileName);
|
||||
try
|
||||
{
|
||||
File.Copy(originalPath, backupPathInSource, false);
|
||||
return backupPathInSource;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
// Ignore and fallback.
|
||||
}
|
||||
catch (IOException ex) when (File.Exists(backupPathInSource))
|
||||
{
|
||||
throw new InvalidOperationException($"备份文件已存在: {backupPathInSource}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var fallbackDirectory = Path.Combine(localAppData, "RevitHttpControl", "Backups");
|
||||
Directory.CreateDirectory(fallbackDirectory);
|
||||
|
||||
var backupPathInFallback = Path.Combine(fallbackDirectory, backupFileName);
|
||||
File.Copy(originalPath, backupPathInFallback, false);
|
||||
return backupPathInFallback;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -367,9 +399,20 @@ namespace RevitHttpControl.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
if (doc.IsModified)
|
||||
if (!doc.IsModified)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
doc.Save();
|
||||
return;
|
||||
}
|
||||
catch (Exception ex) when (IsReadOnlySaveError(ex))
|
||||
{
|
||||
SaveDocumentAsWritableCopy(doc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -378,6 +421,38 @@ namespace RevitHttpControl.Services
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsReadOnlySaveError(Exception ex)
|
||||
{
|
||||
if (ex == null) return false;
|
||||
var message = ex.Message ?? string.Empty;
|
||||
return message.IndexOf("read-only", StringComparison.OrdinalIgnoreCase) >= 0 ||
|
||||
message.IndexOf("只读", StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
}
|
||||
|
||||
private void SaveDocumentAsWritableCopy(Document doc)
|
||||
{
|
||||
var originalPath = doc.PathName;
|
||||
if (string.IsNullOrWhiteSpace(originalPath))
|
||||
throw new InvalidOperationException("文档为只读且无法获取原始路径,不能自动另存为");
|
||||
|
||||
var fileName = Path.GetFileNameWithoutExtension(originalPath);
|
||||
var extension = Path.GetExtension(originalPath);
|
||||
var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
||||
|
||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var outputDirectory = Path.Combine(localAppData, "RevitHttpControl", "Optimized");
|
||||
Directory.CreateDirectory(outputDirectory);
|
||||
|
||||
var outputPath = Path.Combine(outputDirectory, $"{fileName}_optimized_{timestamp}{extension}");
|
||||
var saveAsOptions = new SaveAsOptions
|
||||
{
|
||||
OverwriteExistingFile = false,
|
||||
Compact = true
|
||||
};
|
||||
|
||||
doc.SaveAs(outputPath, saveAsOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文档文件大小
|
||||
/// </summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user