C# 通过WebApi将文件上载到Azure Blob存储,而无需访问本地文件系统
我正在尝试通过web api将文件从本地命令行客户端上载到Azure存储。 我正在使用Azure网站来实现这一点。与客户合作不是问题。我在当地一切都很好。以下是web api代码:C# 通过WebApi将文件上载到Azure Blob存储,而无需访问本地文件系统,c#,azure,asp.net-web-api,azure-storage-blobs,C#,Azure,Asp.net Web Api,Azure Storage Blobs,我正在尝试通过web api将文件从本地命令行客户端上载到Azure存储。 我正在使用Azure网站来实现这一点。与客户合作不是问题。我在当地一切都很好。以下是web api代码: public async Task<HttpResponseMessage> PostUpload() { // need a local resource to store uploaded files temporarily LocalResource
public async Task<HttpResponseMessage> PostUpload()
{
// need a local resource to store uploaded files temporarily
LocalResource localResource = null;
try
{
// Azure web-site fails here
localResource = RoleEnvironment.GetLocalResource("TempStorage");
}
catch (Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Unable to get access to local resources");
}
var provider = new MultipartFormDataStreamProvider(localResource.RootPath);
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// snipped validation code
var container = // code to get container
foreach (var fileData in provider.FileData)
{
var filename = GetBlobName(fileData);
var blob = container.GetBlockBlobReference(filename);
using (var filestream = File.OpenRead(fileData.LocalFileName))
{
blob.UploadFromStream(filestream);
}
File.Delete(fileData.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
public异步任务postpload()
{
//需要本地资源临时存储上载的文件
LocalResource LocalResource=null;
尝试
{
//Azure网站在此失败
localResource=RoleEnvironment.GetLocalResource(“TempStorage”);
}
捕获(例外e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError,“无法访问本地资源”);
}
var provider=新的MultipartFormDataStreamProvider(localResource.RootPath);
//读取表单数据。
wait Request.Content.ReadAsMultipartAsync(提供程序);
//截取的验证码
var container=//获取容器的代码
foreach(provider.fileData中的var fileData)
{
var filename=GetBlobName(fileData);
var blob=container.GetBlockBlobReference(文件名);
使用(var filestream=File.OpenRead(fileData.LocalFileName))
{
blob.UploadFromStream(文件流);
}
Delete(fileData.LocalFileName);
}
返回Request.CreateResponse(HttpStatusCode.OK);
}
当我在本地运行时,一切正常,但一旦我在Azure中部署网站,我就无法上载,因为Azure网站无法访问LocalResource。我需要切换到Azure Web角色。我可以切换,但访问本地文件系统让我很烦恼
MultipartFormDataStreamProvider()的实例需要LocalResource。我还没有找到将文件上传到WebApi的替代方法。我的计划是,不在本地硬盘上存储任何东西
还有其他上传文件的方法吗
p、 我已经看到我可以给客户端应用程序一个带有签名的url,并让客户端直接上传到Azure博客。但我不确定这会有多安全,也不确定将签名传递给客户端会有多安全。目前,我认为客户机将在非常恶劣的环境中运行,从客户机返回的任何东西都不可信
UPD我的最终解决方案涉及使用服务器上发布并传递给客户端的只写共享访问签名。然后客户端将文件直接上传到Azure。这样我就省去了很多管理上传文件的麻烦。这是我的解决方案。这并不是您想要的答案,但您可以使用本地存储和Azure网站,使用MultiPartFileStreamProvider和Path.GetTempPath()。代码应该是这样的
public async Task<HttpResponseMessage> PostUpload()
{
var provider = new MultipartFileStreamProvider(Path.GetTempPath());
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// do the rest the same
}
public异步任务postpload()
{
var provider=new MultipartFileStreamProvider(Path.GetTempPath());
//读取表单数据。
wait Request.Content.ReadAsMultipartAsync(提供程序);
//其余的也一样
}
让您的代码与本地资源保持原样的一个可能解决方案是将其托管在工作进程中,该工作进程通过Owin自行托管web api
您可以在以下位置找到一个简单的演练:
您只需要在RoleEntryPoint的OnStart()方法中启动Owin托管api。请记住,您还可以从web api响应返回Html,这样您就可以使工作人员角色成为非常灵活的基础项目
下面是一个快速片段,展示了如何通过上面的链接设置Owin主机:
private IDisposable _webApp = null;
public override bool OnStart() {
ServicePointManager.DefaultConnectionLimit = 5;
var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["DefaultEndpoint"];
var baseUri = string.Format("{0}://{1}", endpoint.Protocol, endpoint.IPEndpoint);
_webApp = WebApp.Start<Startup>(new StartOptions(baseUri));
return base.OnStart();
}
public override void OnStop() {
if (_webApp != null) {
_webApp.Dispose();
}
base.OnStop();
}
...
using System.Web.Http;
using Owin;
class Startup {
public void Configuration(IAppBuilder app) {
var config = new HttpConfiguration();
config.Routes.MapHttpRoutes("Default", "{controller}/{id}",
new { id = RouteParameter.Optional });
app.UseWebApi(config);
}
}
private IDisposable _webApp=null;
公共覆盖bool OnStart(){
ServicePointManager.DefaultConnectionLimit=5;
var endpoint=RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[“DefaultEndpoint”];
var baseUri=string.Format(“{0}://{1}”,endpoint.Protocol,endpoint.IPEndpoint);
_webApp=webApp.Start(新的StartOptions(baseUri));
返回base.OnStart();
}
公共覆盖void OnStop(){
如果(_webApp!=null){
_Dispose();
}
base.OnStop();
}
...
使用System.Web.Http;
使用Owin;
类启动{
公共无效配置(IAppBuilder应用程序){
var config=新的HttpConfiguration();
config.Routes.MapHttpRoutes(“默认值”、“{controller}/{id}”,
新的{id=RouteParameter.Optional});
app.UseWebApi(配置);
}
}
我发现了这篇StackOverflow文章,它覆盖了MultipartFormDataStreamProvider,因此文件不会首先存储在本地,而是直接写入AWSStream。见:
但我必须说,我也喜欢trailmax的解决方案。以下代码“localResource=RoleEnvironment.GetLocalResource(“TempStorage”)引发了什么异常?您对使用REST API感到满意吗?@BrianDishaw该异常与“无法获取LocalResource、System.Runtime.InteropServices.SehexException(0x80004005):外部组件引发了异常。”。此外,此页()建议本地资源仅用于Web和工作者角色,而不用于Web站点。@VJD是的,有点。我想必须咬紧牙关,生成共享访问签名并将其传递给客户端,然后客户端通过签名将文件直接上载到Azure。你可能可以在这篇文章中看到我的答案:……我不知道我已经专门讨论了上传到Azure,但它可能会给你一个好主意在网站中,这有多可靠。它不能通过大文件上传中途删除吗?我已经删除了表明临时目录不是临时目录的死链接。据我所知,这仍然是事实。我可以将网站部署为web角色,并拥有可用的本地资源。部署JU