Office 365 文档查看器 - 不适用于 Azure 存储共享访问 url?

Office 365 document viewer - doesn't work with azure storage shared access url?

这里整洁 url 将允许您查看任何 public/web 可访问的单词、excel、powerpoint 等。可以在线查看文档:

https://view.officeapps.live.com/op/view.aspx?src=URL_TO_YOUR_FILE

我已经成功地将它用于存储在具有 public 访问权限的容器中的 azure blob 存储中的文档。但是,如果我尝试将文档 url 用于私有容器中的文件(使用共享访问签名 url),我会收到一条错误消息,指出找不到该文件。

与 google docs 文档查看器相同的问题:

https://docs.google.com/viewer?

如何使用私人文件(使用共享访问签名 urls)?

编辑

有趣的是,如果我使用从共享访问签名创建的 tinyurl URL,它就可以工作。

How can I get this working with private files (using shared access signature urls)?

根据你的描述,我在自己这边测试了一下,重现了这个问题。正如 View Office documents in a browser 提到的那样,需要进行 URL 编码,并且文档必须可以在 Internet 上公开访问。

一个简单的方法是,您可以通过此 official tool 创建在线文档 URL。另外,您可以自己创建 URL,如下所示:

https://view.officeapps.live.com/op/view.aspx?src=URLEncode(URL_TO_YOUR_FILE)

This is a sample code for office documents preview in the browser (PPTX, XLXS, XLS, PPT, DOC , DOCX ) & PDF when Azure blob storage containers are private level access.

private static string GetContainerSharedAccessSignature(CloudBlockBlob blob, string fileName)
    {
        string contentType = "";
        var headers = new SharedAccessBlobHeaders
        {
            ContentDisposition = $"attachment;filename={fileName}",
        };

        if (fileName.Contains(".xlsx"))
            contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        else if (fileName.Contains(".docx"))
            contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        else if (fileName.Contains(".pptx"))
            contentType = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
        else if (fileName.Contains(".doc"))
            contentType = "application/msword";
        else if (fileName.Contains(".xls"))
            contentType = "application/vnd.ms-excel";
        else if (fileName.Contains(".ppt"))
            contentType = "application/vnd.ms-powerpoint";
        else if (fileName.Contains(".rtf"))
            contentType = "application/rtf";
        else if (fileName.Contains(".jpg"))
            contentType = "image/jpg";
        else if (fileName.Contains(".jpeg"))
            contentType = "image/jpeg";
        else if (fileName.Contains(".png"))
            contentType = "image/png";
        else if (fileName.Contains(".gif"))
            contentType = "image/gif";
        else if (fileName.Contains(".bmp"))
            contentType = "image/bmp";
        else if (fileName.Contains(".tif"))
            contentType = "image/tif";
        else
            contentType = "application/octet-stream";

        if (!string.IsNullOrWhiteSpace(contentType))
        {
            headers.ContentType = contentType;
        }

        var signature =
            blob.GetSharedAccessSignature(
                new SharedAccessBlobPolicy
                {
                    Permissions = SharedAccessBlobPermissions.Read,
                    SharedAccessExpiryTime = DateTime.Now.AddMinutes(10)
                },
                headers);

        return Uri.EscapeDataString($"{blob.StorageUri.PrimaryUri.AbsoluteUri}{signature}");
    }

  public string GenerateSASToken(string containerName, string fileName)
    {
        CloudBlobContainer cloudBlobContainer = null;
        try
        {
            CloudBlobClient cloudBlobClient = searchConfig.CloudBlobClient;
            cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            var blob = cloudBlobContainer.GetBlockBlobReference(fileName);
            return GetContainerSharedAccessSignature(blob, fileName);
        }
        catch (Exception)
        {
            throw;
        }
    }


 [HttpGet("bloburl/{fileName}/{container}")]
    public IActionResult BlobSASTokenURL(string fileName, string container)
    {
        try
        {
            if (string.IsNullOrEmpty(fileName))
            {
                _logger.Log(LogLevel.Warning, $"file name {fileName} is missing.");
                return UnprocessableEntity();
            }

            if (string.IsNullOrEmpty(container))
            {
                _logger.Log(LogLevel.Warning, $"container name {fileName} is missing.");
                return UnprocessableEntity();
            }

            var tokenUrl = blobStorageService.GenerateSASToken(container, fileName);
            var token = new { tokenUrl };
            return Ok(token);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.Message);
            return StatusCode(500, $"Failed to generate token url for {fileName} .");
        }
    }

front end

 import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { environment } from '../../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class SearchService {

    public getBlobSASUrl(fileName: string, containerName: string): Observable<any> {
    return this.repository.get(environment.apiBaseURL, 'api/BlobStorage/sastoken/' + fileName + '/' + containerName)
    .pipe(map((res: any) => {
         return res.tokenUrl;
        }));


    }}

Component

 import { UrlService } from './shared/search.service';

@Component({
  templateUrl: './filePreview.component.html',
  styleUrls: [],
  providers: [ DatePipe ]
})
export class filePreviewComponent implements OnInit {

     constructor(private urlService: UrlService, public sanitizer: DomSanitizer, public datepipe: DatePipe) {

  }

     showFilePreview(fileName: string, containerName: string, fileContentType: string) {
    this.urlService.getBlobSASUrl(result.document.fileName, result.document.containerName).subscribe(results => {
          result.document.fileURL = this.sanitizer.bypassSecurityTrustResourceUrl('https://view.officeapps.live.com/op/embed.aspx?src='+results+'&embedded=true');
          result.document.toggle =! result.document.toggle;
        });
  }

}

HTML

  <div id="divpreview" class="preview_container_wrapper" *ngIf="result.document.toggle && result.document.containerName != null">
      <div class="col-md preview_container" id="dvpreviewcol">
        <iframe *ngIf="FileType !== 'PDF';"
          [src]='fileURL'
          class="preview_iframe"></iframe>
        <object *ngIf="FileType === 'PDF';" [data]="fileURL | safeUrl" type="application/pdf">Preview not available</object>
      </div>
    </div>