Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting attachments and uploading them to a different page #56

Open
dostjh opened this issue Dec 21, 2021 · 3 comments
Open

Getting attachments and uploading them to a different page #56

dostjh opened this issue Dec 21, 2021 · 3 comments

Comments

@dostjh
Copy link

dostjh commented Dec 21, 2021

We have a use case where we want to download content from a variety of spaces and re-upload them as copied pages to a centralized space. The one issue I'm having thus far is copying attachments.

var sourceAttachments = _client.Attachment.GetAttachmentsAsync(sourcePage.Id).Result; foreach (var attachment in sourceAttachments) { _client.Attachment.AttachAsync(targetPage.Id, attachment, attachment.Title, contentType:attachment.Metadata.MediaType); }

When I've uploaded attachments fresh, I've been able to create a bitmap and then upload that as a stream. However, I'm not seeing where the stream is for the attachments I'm getting from the source space.

I may be able to work around this by Downloading and then reuploading the attachment, but naively I'd expect GetAttachmentsAsync and AttachAsync to be able to work in tandem without recreating the file data wholecloth.

@dostjh
Copy link
Author

dostjh commented Dec 21, 2021

I have been able to work around this for now by specifying a new WebClient with appropriate authorization headers and downloading the file directly into a byte array. For example:

		foreach (var attachment in sourceAttachments)
		{
			var targetAttachment = targetAttachments.FirstOrDefault(a => a.Title == attachment.Title);
			try
			{
				var downloadLink = _confluenceUrl.TrimEnd('/') + attachment.Links.Download;
				var webClient = new WebClient();
				webClient.Headers.Add(HttpRequestHeader.Authorization, "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes($"{_alias}:{_password}")).ToString());
				webClient.Headers.Add(HttpRequestHeader.ContentType, "application/json");
				var downloadData = webClient.DownloadData(downloadLink);

				if (targetAttachment != null)
				{
					var attachResult = _client.Attachment.UpdateDataAsync(targetPage.Id, targetAttachment.Id, downloadData, attachment.Title, contentType: attachment.Metadata.MediaType);
				}
				else
				{
					var attachResult = _client.Attachment.AttachAsync(targetPage.Id, downloadData, attachment.Title, contentType: attachment.Metadata.MediaType).Result;
				}
				
				webClient.Dispose();
			}
			catch
			{
				// As you please
			}
		}

@Lakritzator
Copy link
Member

I hope I understand it correctly, you would like to download an attachment and use that again to upload it to a different page.
Hmm, yes I see what you mean with going hand in hand, it just isn't a use-case I though of.

As a workaround you can use a memory stream to download the attachment.

foreach (var attachment in sourceAttachments)
{
  var attachmentStream = await _client.Attachment.GetContentAsync<MemoryStream>(attachment);
  // not 100% sure you need this, but reset the stream to the begining.
  attachmentMemoryStream.Seek(0, SeekOrigin.Begin);
  await _client.Attachment.AttachAsync(targetPage.Id, memoryStream, attachment.Title, contentType: attachment.Metadata.MediaType);
}

Is that need still valid, if I provide the copy page function which should even be able to copy attachments?

P.S.
I see that you are not using async code to use my API, using ".Result" is not the best practice.
Is there a reason not to use async/await? I can really recommend to do so.

@dostjh
Copy link
Author

dostjh commented Dec 21, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants