in Common/Migration/Phase2/Processors/AttachmentsProcessor.cs [118:206]
private async Task<AttachmentLink> UploadAttachmentFromSourceRelation(IMigrationContext migrationContext, IBatchMigrationContext batchContext, WorkItem sourceWorkItem, WorkItemRelation sourceRelation, int maxAttachmentSize)
{
//Attachments are of type Rel = "AttachedFile"
if (sourceRelation.Rel == Constants.AttachedFile)
{
string filename = null;
string comment = null;
long resourceSize = 0;
//get the file name and comment
if (sourceRelation.Attributes.ContainsKey(Constants.RelationAttributeName))
{
filename = sourceRelation.Attributes[Constants.RelationAttributeName].ToString();
}
if (sourceRelation.Attributes.ContainsKey(Constants.RelationAttributeComment))
{
comment = sourceRelation.Attributes[Constants.RelationAttributeComment].ToString();
}
//get the guid from the url
Guid attachmentId;
if (Guid.TryParse(sourceRelation.Url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last(), out attachmentId))
{
Stream stream = null;
try
{
Logger.LogTrace(LogDestination.File, $"Reading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
stream = await WorkItemTrackingHelpers.GetAttachmentAsync(migrationContext.SourceClient.WorkItemTrackingHttpClient, attachmentId);
Logger.LogTrace(LogDestination.File, $"Completed reading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
}
catch (Exception e)
{
Logger.LogError(LogDestination.File, e, $"Unable to download attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
ClientHelpers.AddFailureReasonToWorkItemMigrationState(sourceWorkItem.Id.Value, FailureReason.AttachmentDownloadError, batchContext.WorkItemMigrationState);
return null;
}
AttachmentReference aRef = null;
using (MemoryStream memstream = new MemoryStream())
{
using (stream)
{
try
{
Logger.LogTrace(LogDestination.File, $"Downloading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
await ClientHelpers.CopyStreamAsync(stream, memstream);
Logger.LogTrace(LogDestination.File, $"Completed downloading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
}
catch (Exception e)
{
Logger.LogError(LogDestination.File, e, $"Unable to read downloaded attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
ClientHelpers.AddFailureReasonToWorkItemMigrationState(sourceWorkItem.Id.Value, FailureReason.AttachmentDownloadError, batchContext.WorkItemMigrationState);
return null;
}
}
resourceSize = memstream.Length;
if (resourceSize > maxAttachmentSize)
{
Logger.LogWarning(LogDestination.File, $"Attachment of source work item with id {sourceWorkItem.Id} and url {sourceRelation.Url} exceeded the maximum attachment size of {maxAttachmentSize} bytes." +
$" Skipping creating the attachment in target account.");
return null;
}
memstream.Position = 0;
//upload the attachment to the target
try
{
Logger.LogTrace(LogDestination.File, $"Uploading attachment {filename} of {resourceSize} bytes for source work item {sourceWorkItem.Id} from the source account");
aRef = await WorkItemTrackingHelpers.CreateAttachmentChunkedAsync(migrationContext.TargetClient.WorkItemTrackingHttpClient, migrationContext.TargetClient.Connection, memstream, migrationContext.Config.AttachmentUploadChunkSize);
Logger.LogTrace(LogDestination.File, $"Completed uploading attachment {filename} for source work item {sourceWorkItem.Id} from the source account");
}
catch (Exception e)
{
Logger.LogError(LogDestination.File, e, $"Unable to upload attachment {filename} for source work item {sourceWorkItem.Id} to the target account");
ClientHelpers.AddFailureReasonToWorkItemMigrationState(sourceWorkItem.Id.Value, FailureReason.AttachmentUploadError, batchContext.WorkItemMigrationState);
}
}
if (aRef != null)
{
return new AttachmentLink(filename, aRef, resourceSize, comment);
}
}
else
{
Logger.LogError(LogDestination.File, $"Attachment link is incorrect for {sourceWorkItem.Id} {sourceRelation.Url}. Skipping creating the attachment in target account.");
ClientHelpers.AddFailureReasonToWorkItemMigrationState(sourceWorkItem.Id.Value, FailureReason.AttachmentUploadError, batchContext.WorkItemMigrationState);
}
}
return null;
}