C# 如何传递Forge bucket下载*绕过*web应用,而不是通过*web应用?
我有一个基于此示例的Azure托管web应用程序: 此示例演示了一个桌面应用程序,其中显示了BIM 360团队、BIM 360文档和Fusion团队中心,它们分别包含项目、文件夹、项目和版本。对于每个版本,都可以使用查看器进行查看 (出于安全目的,托管应用程序用作中介。) 我扩展了这个示例,以便可以将项目和版本对象下载到桌面。这很有效 要下载的对象/文件将作为C# 如何传递Forge bucket下载*绕过*web应用,而不是通过*web应用?,c#,download,autodesk-forge,asp.net-apicontroller,autodesk-data-management,C#,Download,Autodesk Forge,Asp.net Apicontroller,Autodesk Data Management,我有一个基于此示例的Azure托管web应用程序: 此示例演示了一个桌面应用程序,其中显示了BIM 360团队、BIM 360文档和Fusion团队中心,它们分别包含项目、文件夹、项目和版本。对于每个版本,都可以使用查看器进行查看 (出于安全目的,托管应用程序用作中介。) 我扩展了这个示例,以便可以将项目和版本对象下载到桌面。这很有效 要下载的对象/文件将作为HttpResponseMessage从Autodesk服务器检索 using System; using System.Net; usi
HttpResponseMessage
从Autodesk服务器检索
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);
}
}
}
}
是否可以在Azure应用程序周围传递大部分有效负载,以便对象/文件完好无损地到达,安全性得到维护,但是应用程序的数据余量没有被破坏?您可以为对象创建一个
签名URL
,并将其传递到后端,基本上,签名URL是指向对象的链接,允许临时匿名访问-有关详细信息,请参阅
或者,您可以将对象下载到一个临时位置(请参阅和),并传递路径信息,以便在再次下载时保存代码的其他部分。您可以尝试从rest API返回一个元组(bucketUri、userAccessToken),而不是从bucket下载的内容。然后使用RESTAPI中的相同代码在桌面客户机上下载bucket,以便download@dvitel这需要将accessToken传递给桌面客户端,不是吗?我正试图避免这种情况。谢谢你,布莱恩。我尝试了签名URL方法,但得到了403禁止响应。(我更改了范围以包括数据:写入、使用POST方法和使用签名端点。)可能是因为:“成功调用此端点需要bucket owner访问权限。”我正在尝试下载模型、衍生工具等。您提到的备选方案与我当前的工作流程没有太大区别;它仍然需要将数据带到内存或虚拟磁盘中的临时位置。确保使用客户端id/secret的Forge应用程序在为对象创建签名URL时拥有目标存储桶-只需在我存储桶中的对象上进行了尝试,就成功了:
{“signedUrl”:"https://developer.api.autodesk.com/oss/v2/signedresources/7012e598-dc2b-4aee-b8df-8ed968021170?region=US,“过期”:156860960947,“单一使用”:false}
我想将其用于BIM360模型和衍生产品,因此我绝对不是桶的所有者。还有其他想法吗?还有其他想法吗?让我与工程部谈谈,看看是否有办法解决许可问题。
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);