Javascript Angular/WebApi-仅当我不上传到Azure存储时,在浏览器中显示PDF才有效

Javascript Angular/WebApi-仅当我不上传到Azure存储时,在浏览器中显示PDF才有效,javascript,angularjs,azure,pdf,asp.net-web-api,Javascript,Angularjs,Azure,Pdf,Asp.net Web Api,目标:发布一个PDF文件,将其blob内容存储在Azure存储中,然后立即将其内容恢复到浏览器中显示 什么有效:因此,我有以下代码,成功地调用带有PDF文件内容的控制器POST方法,并返回带有浏览器中显示内容的响应 角度/html: //html <object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>

目标:发布一个PDF文件,将其blob内容存储在Azure存储中,然后立即将其内容恢复到浏览器中显示

什么有效:因此,我有以下代码,成功地调用带有PDF文件内容的控制器POST方法,并返回带有浏览器中显示内容的响应

角度/html

//html
<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>

//angular controller
...
.success(function (data) {
   console.log(data);
   var file = new Blob([(data)], { type: 'application/pdf' });
   var fileURL = URL.createObjectURL(file);
   $scope.content = $sce.trustAsResourceUrl(fileURL);
}
    // POST api/<something>/Upload
    [Authorize]
    [HttpPost]
    [Route("Upload")]
    public async Task<HttpResponseMessage> Post()
    {
        try
        {
            HttpRequestMessage request = this.Request;
            if (!request.Content.IsMimeMultipartContent())
            {
                return new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType);
                //return StatusCode(HttpStatusCode.UnsupportedMediaType);
            }

            var customMultipartFormDataProvider = new CustomMultipartFormDataProvider();

            var provider = await request.Content.ReadAsMultipartAsync<CustomMultipartFormDataProvider>(customMultipartFormDataProvider);
            //contents[1] and //contents[2] were StreamContent of the FormData
            var fileContent = provider.Contents[2];
            var formData = provider.FormData;

            //can succesfully write to a SQL database here without fail

            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            response.Content = fileContent;
            return response;
    } 

  public class CustomMultipartFormDataProvider : MultipartFormDataRemoteStreamProvider
  {
    public override RemoteStreamInfo GetRemoteStream(HttpContent parent, HttpContentHeaders headers)
    {
        return new RemoteStreamInfo(
            remoteStream: new MemoryStream(),
            location: string.Empty,
            fileName: string.Empty);
    }
  }
//html
//角度控制器
...
.成功(功能(数据){
控制台日志(数据);
var file=newblob([(数据)],{type:'application/pdf'});
var fileURL=URL.createObjectURL(文件);
$scope.content=$sce.trustAsResourceUrl(fileURL);
}
WebAPI控制器

//html
<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>

//angular controller
...
.success(function (data) {
   console.log(data);
   var file = new Blob([(data)], { type: 'application/pdf' });
   var fileURL = URL.createObjectURL(file);
   $scope.content = $sce.trustAsResourceUrl(fileURL);
}
    // POST api/<something>/Upload
    [Authorize]
    [HttpPost]
    [Route("Upload")]
    public async Task<HttpResponseMessage> Post()
    {
        try
        {
            HttpRequestMessage request = this.Request;
            if (!request.Content.IsMimeMultipartContent())
            {
                return new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType);
                //return StatusCode(HttpStatusCode.UnsupportedMediaType);
            }

            var customMultipartFormDataProvider = new CustomMultipartFormDataProvider();

            var provider = await request.Content.ReadAsMultipartAsync<CustomMultipartFormDataProvider>(customMultipartFormDataProvider);
            //contents[1] and //contents[2] were StreamContent of the FormData
            var fileContent = provider.Contents[2];
            var formData = provider.FormData;

            //can succesfully write to a SQL database here without fail

            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            response.Content = fileContent;
            return response;
    } 

  public class CustomMultipartFormDataProvider : MultipartFormDataRemoteStreamProvider
  {
    public override RemoteStreamInfo GetRemoteStream(HttpContent parent, HttpContentHeaders headers)
    {
        return new RemoteStreamInfo(
            remoteStream: new MemoryStream(),
            location: string.Empty,
            fileName: string.Empty);
    }
  }
//POST-api//上传
[授权]
[HttpPost]
[路由(“上传”)]
公共异步任务Post()
{
尝试
{
HttpRequestMessage request=此.request;
如果(!request.Content.IsMimeMultipartContent())
{
返回新的HttpResponseMessage(HttpStatusCode.UnsupportedMediaType);
//返回状态码(HttpStatusCode.UnsupportedMediaType);
}
var customMultipartFormDataProvider=新的customMultipartFormDataProvider();
var provider=wait request.Content.ReadAsMultipartAsync(customMultipartFormDataProvider);
//内容[1]和//内容[2]是FormData的StreamContent
var fileContent=provider.Contents[2];
var formData=provider.formData;
//可以在此处成功写入SQL数据库而不会失败
HttpResponseMessage response=新的HttpResponseMessage(HttpStatusCode.OK);
response.Content=fileContent;
返回响应;
} 
公共类CustomMultipartFormDataProvider:MultipartFormDataRemoteStreamProvider
{
公共覆盖RemoteStreamInfo GetRemoteStream(HttpContent父级,HttpContentHeaders标头)
{
返回新的RemoteStreamInfo(
remoteStream:新的MemoryStream(),
位置:string.Empty,
文件名:string.Empty);
}
}
问题:但是,如果我添加代码行以将此内容上载到Azure存储,则无法工作:

  string blobStorageConnectionString = ConfigurationManager.ConnectionStrings["AzureStorageAccount"].ConnectionString;
  CloudStorageAccount blobStorageAccount = CloudStorageAccount.Parse(blobStorageConnectionString);
  CloudBlobClient blobClient = blobStorageAccount.CreateCloudBlobClient();
  CloudBlobContainer container = blobClient.GetContainerReference(<containerName>);
  container.CreateIfNotExists();
  CloudBlockBlob block = container.GetBlockBlobReference(<keyname>);
  block.UploadFromStream(await fileContent.ReadAsStreamAsync());
string blobStorageConnectionString=ConfigurationManager.ConnectionStrings[“AzureStorageAccount”]。ConnectionString;
CloudStorageAccount blobStorageAccount=CloudStorageAccount.Parse(blobStorageConnectionString);
CloudBlobClient blobClient=blobStorageAccount.CreateCloudBlobClient();
CloudBlobContainer容器=blobClient.GetContainerReference();
container.CreateIfNotExists();
CloudBlockBlob block=container.GetBlockBlobReference();
block.UploadFromStream(等待fileContent.ReadAsStreamAsync());
问题是它成功地上传到存储,控制流甚至到达webapi控制器中的return语句,但它几乎不返回


console.log(data)在我的控制器中的success函数上从未被调用。return语句似乎不会执行,即使它的行为与之类似。

如注释中所述,
(通常)(因为它们毕竟是对数据流的抽象)。您可以先将流写入
内存流
,然后将该流(可以重新定位)用于Blob上载和响应。一个小概念示例:

//copy stream
var ms = new MemoryStream();
await fileContent.CopyToAsync(ms);

//other stuff

//upload to blob storage
ms.Position = 0;
block.UploadFromStream(ms);

//other stuff

//set response content
ms.Position = 0;
response.Content = new StreamContent(ms);
不过,我建议您另一种方法:与其直接返回blob的内容,不如将上载blob的URI返回给客户端?这样,客户端就可以决定是否下载该文件,或者干脆忽略它,然后将流量和带宽从应用程序卸载到Azure blob服务。您可以允许使用SAS生成的令牌(共享访问签名)在有限的时间内访问blob:

参考资料:


您确定文件内容流可以重复使用吗?至少,我认为您必须将位置重置为0,并且更有可能需要读入MemoryStream。您能否澄清“重复使用”是什么意思?是因为我在将文件内容上载到存储时读取了带有“位置”的内容吗发生更改?我在哪里可以找到位置上的文档?很抱歉,如果noob质疑它是一个流。每个流都有一个位置。通常不能重用流。