【发布时间】:2020-01-13 22:34:17
【问题描述】:
我有一个基于此示例的 Azure 托管 Web 应用:https://github.com/Autodesk-Forge/data.management-csharp-desktop.sample
此示例演示了一个桌面应用程序,该应用程序显示了 BIM 360 Team、BIM 360 Docs 和 Fusion Team 中心,它们各自的项目、文件夹、项目和版本。每个版本都可以使用 Viewer 查看。
(出于安全目的,托管应用程序用作中介。)
我已扩展此示例,以便可以将项目和版本对象下载到桌面。这行得通。
要下载的对象/文件从 Autodesk 服务器检索为 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);
}
}
}
}
这个响应然后被传递到桌面应用程序,然后转换为字节:
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}");
}
}
然后以文件的形式保存到硬盘,使用如下方式:
byte [] bytes = await Forge.DataManagement.GetDownload(bucketKey, objectName);
System.IO.File.WriteAllBytes(pathAndFilename, bytes);
是否可以在 Azure 应用程序周围传递大部分有效负载 以便对象/文件完好无损地到达,保持安全性,但应用程序的数据限额不会被耗尽?
【问题讨论】:
-
您可以尝试从 rest API 返回不是从存储桶下载的内容,而是一个元组 (bucketUri, userAccessToken) 。然后使用来自 REST API 的相同代码在桌面客户端上执行存储桶的下载
-
@dvitel 这将涉及将 accessToken 传递给桌面客户端,不是吗?我试图避免这种情况。
标签: c# download autodesk-forge asp.net-apicontroller autodesk-data-management