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>
这里整洁 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>