I have an Azure hosted web app based on this sample: https://github.com/Autodesk-Forge/data.management-csharp-desktop.sample
This sample demonstrates a desktop application that shows BIM 360 Team, BIM 360 Docs and Fusion Team hubs, which respective Projects, Folders, Items and Versions. For each version it is possible to view it using Viewer.
(The hosted app is used as an intermediary for security purposes.)
I have extended this sample so that the item and version objects can be downloaded to the desktop. This works.
The object/file to download is retrieved from the Autodesk server as an HttpResponseMessage
.
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Autodesk.Forge;
namespace FPD.Sample.Cloud.Controllers
{
public class DownloadController : ApiController
{
private const string FORGE_BASE_URL = "https://developer.api.autodesk.com";
private const string PROXY_ROUTE = "api/forge/download/";
// HttpClient has been designed to be re-used for multiple calls.
// Even across multiple threads.
// https://stackoverflow.com/a/22561368/4838205
private static HttpClient _httpClient;
[HttpGet]
[Route("api/forge/download/{bucketKey}/{objectName}/bucket")]
public async Task<HttpResponseMessage> Get(string bucketKey, string objectName)
{
string sessionId, localId;
if (!HeaderUtils.GetSessionLocalIDs(out sessionId, out localId)) return null;
if (!await OAuthDB.IsSessionIdValid(sessionId, localId)) return null;
string userAccessToken = await OAuthDB.GetAccessToken(sessionId, localId);
if (_httpClient == null)
{
_httpClient = new HttpClient(
// this should avoid HttpClient searching for proxy settings
new HttpClientHandler()
{
UseProxy = false,
Proxy = null
}, true);
_httpClient.BaseAddress = new Uri(FORGE_BASE_URL);
ServicePointManager.DefaultConnectionLimit = int.MaxValue;
}
string resourceUrl = $"/oss/v2/buckets/{bucketKey}/objects/{objectName}";
try
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceUrl);
// add our Access Token
request.Headers.Add("Authorization", "Bearer " + userAccessToken);
HttpResponseMessage response = await _httpClient.SendAsync(request,
// this ResponseHeadersRead force the SendAsync to return
// as soon as the header is ready, faster
HttpCompletionOption.ResponseHeadersRead);
return response;
}
catch
{
return new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);
}
}
}
}
This response is then passed to the desktop application, then converted to bytes:
public async static Task<byte[]> GetDownload(string bucketKey, string objectName)
{
byte[] bytes = await RestAPI<byte[]>.RequestAsyncBytes("api/forge/download/" + bucketKey + "/" + objectName + "/bucket", true);
return bytes;
}
public static async Task<byte[]> RequestAsyncBytes(string endpoint, IDictionary<string, string> headers, bool includeIdHeaders)
{
var client = new RestClient(EndPoints.BaseURL);
var request = new RestRequest(endpoint, Method.GET);
if (includeIdHeaders)
{
if (headers == null) headers = new Dictionary<string, string>();
headers.Add("FPDSampleSessionId", SessionManager.SessionId);
headers.Add("FPDSampleLocalId", SessionManager.MachineId);
}
if (headers != null)
foreach (KeyValuePair<string, string> header in headers)
request.AddHeader(header.Key, header.Value);
IRestResponse response = await client.ExecuteTaskAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return response.RawBytes;
}
else if (response.StatusCode == System.Net.HttpStatusCode.NoContent)
{
throw new Exception("No Content: " + endpoint);
}
else if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
throw new Exception("Not found: " + endpoint);
}
else
{
throw new Exception($"Error {response.StatusCode}. Cannot call {endpoint}");
}
}
Then saved to the hard drive as a file, using something like this:
byte [] bytes = await Forge.DataManagement.GetDownload(bucketKey, objectName);
System.IO.File.WriteAllBytes(pathAndFilename, bytes);
Is it possible to pass the majority of the payload around the Azure app so that the object/file arrives intact, the security is maintained, but the data allowance of the app isn't blown out?