11

当我使用共享访问签名 (SAS) Token构建 URL 时,我目前遇到了 Azure 文件存储问题。该文件将在浏览器中下载,但内容类型始终为 application/octet-stream,而不是更改以匹配文件的 mime 类型。如果我将文件放在 Azure BLOB 存储中并使用 SAS 令牌构建 URL,它会为我的文件发送正确的内容类型 (image/jpeg)。

我已经将我的存储帐户从 V1 升级到 V2 认为这是问题所在,但它并没有解决它。

有没有人知道我可以尝试什么可以让 Azure 文件存储使用带有 SAS 令牌的 URL 返回正确的内容类型来下载文件?

4

9 回答 9

4

如果未提供任何内容,Azure blob 将使用默认值“application/octet-stream”。为了获得正确的 mimetypes,这是我对我的烧瓶应用程序所做的:

@app.route('/', methods=['GET', 'POST'])
def upload_file():
        if request.method == 'POST':
            f = request.files['file']
            mime_type = f.content_type
            print (mime_type)
            print (type(f))
            try:
                blob_service.create_blob_from_stream(container, f.filename, f,
                content_settings=ContentSettings(content_type=mime_type))
            except Exception as e:
                print (str(e))
                pass

mime_type 被传递给 ContentSettings 以获取上传到 azure blob 的文件的当前 mimetypes。

在 nodeJS 中:

blobService.createBlockBlobFromStream(container, blob, stream, streamLength, { contentSettings: { contentType: fileMimeType } }, callback)

在哪里:

fileMimeType是上传文件的类型

callback是你的回调实现

参考使用的方法: https ://docs.microsoft.com/en-us/javascript/api/azure-storage/azurestorage.services.blob.blobservice.blobservice?view=azure-node-latest#createblockblobfromstream-string--字符串--流可读--数字--createblockblobrequestoptions--errororresult-blobresult--

于 2019-01-08T02:43:49.917 回答
4

当我通过门户将 jpeg 文件上传到文件共享时,内容类型更改为application/octet-stream确实。但我无法重现您的下载问题。

我没有在我的 SAS 请求 uri 中指定内容类型,但文件只是作为 jpeg 文件下载。已经在 SDK(帐户 SAS/存储访问策略/文件本身的 SAS)或 REST API 中进行了测试,即使没有内容类型也可以工作。

您可以尝试使用以下代码指定内容类型。

 SharedAccessFileHeaders header = new SharedAccessFileHeaders()
 {
     ContentDisposition = "attachment",
     ContentType = "image/jpeg"
 };
string sasToken = file.GetSharedAccessSignature(sharedPolicy,header);
于 2018-05-03T09:59:17.890 回答
2

到目前为止,这些是我发现的内容类型的唯一修复:

  1. 使用 Microsoft Azure 存储资源管理器手动修改内容类型字符串。您必须右键单击文件和左键单击属性才能显示对话框。
  2. 使用 Microsoft 的 WindowsAzure.Storage Nuget 包以编程方式修改文件。
  3. 通过我自己的网站下载 Surface 文件,不允许直接访问。

对我来说,这些都不是可以接受的选择。如果用户通过门户或 Microsoft Azure Storage Explore 上传文件并忘记更改内容类型,前两个可能会导致错误。我也不想编写 Azure Functions 或 Web 作业来监视和解决此问题。

由于通过 Microsoft Azure Storage Explore 或通过门户上传时,blob 存储没有相同的问题,因此成本要低得多,并且都可以使用 SAS 令牌,因此我们正在转向 blob 存储。我们确实失去了将驱动器安装到本地计算机并使用 Beyond Compare 之类的东西进行文件比较的能力,但这是我们可以忍受的缺点。

如果有人有比上述解决此问题的解决方案更好的解决方案,我将很乐意投票。但是,我认为微软必须做出改变才能解决这个问题。

于 2018-04-30T15:13:48.690 回答
1

看看这个 - Microsoft SAS 示例

如果您不想在 Azure 中更新文件的内容类型,或者更新所有现有文件的内容类型太麻烦,您可以将所需的内容类型与 SAS 令牌传递为出色地。rsct参数是您指定所需内容类型的地方

例如 - https://myaccount.file.core.windows.net/pictures/somefile.pdf?sv=2015-02-21&st=2015-07-01T08:49Z&se=2015-07-02T08:49Z&sr=c&sp=r&rscd=文件;%20附件&rsct=应用%2Fpdf&sig=YWJjZGVmZw%3d%3d&sig=a39%2BYozJhGp6miujGymjRpN8tsrQfLo9Z3i8IRyIpnQ%3d

于 2021-09-08T20:25:28.843 回答
0

这适用于使用 com.microsoft.azure azure-storage 库的 java。上传到共享访问签名资源。

        InputStream is = new FileInputStream(file);
        CloudBlockBlob cloudBlockBlob = new CloudBlockBlob(new URI(sasUri));
        cloudBlockBlob.getProperties().setContentType("application/pdf");
        cloudBlockBlob.upload(is, file.length());
        is.close();

在此处输入图像描述

于 2020-10-05T15:10:15.227 回答
0

我没有尝试过,但理想情况下,您可以使用 ClientOptions 指定不同的标头。它看起来像这样:

ClientOptions options = new ClientOptions();
HttpHeader httpHeaders = new HttpHeader("Content-Type", "application/pdf");
options.setHeaders(Collections.singleton(httpHeaders));
    
blobClient = new BlobClientBuilder()
                .endpoint(<SAS-URL>)
                .blobName("hello")
                .clientOptions(options)
                .buildClient();
于 2021-09-27T04:50:40.407 回答
0
// here you define your file content type
CloudBlockBlob cloudBlockBlob = container.GetBlockBlobReference(file.FileName);
                cloudBlockBlob.Properties.ContentType = file.ContentType; //content type
于 2020-02-18T18:45:24.693 回答
0

对于希望使用声明的内容类型正确上传文件的任何人,v12 客户端已更改设置内容类型。您可以使用 ShareFileHttpHeaders 参数file.Create

ShareFileClient file = directory.GetFileClient(fileName);          
using FileStream stream = File.OpenRead(@"C:\Temp\Amanita_muscaria.jpg");           
file.Create(stream.Length, new ShareFileHttpHeaders { ContentType = ContentType(fileName) });           
file.UploadRange(new HttpRange(0, stream.Length),stream);

ContentType(fileName)文件名的评估在哪里,例如:

if (fileName.EndsWith(".txt")) return "text/plain";
// etc
于 2021-02-17T12:02:10.240 回答
0

我知道我没有回答这个问题,但我相信答案是适用的。我在存储帐户方面遇到了同样的问题,我需要将其作为静态网站。每当我将 blob 上传到容器时,默认类型是“application/octet-stream”,因此 index.html 会被下载而不是显示。

要更改文件类型,请执行以下操作:

# Get Storage Account for its context
$storageAccount = Get-AzStorageAccount -ResourceGroupName <Resource Group Name> -Name <Storage Account Name>
# Get Blobs inside container of storage account
$blobs = Get-AzStorageBlob -Context $storageAccount.Context -Container <Container Name>
foreach ($blob in $blobs) {
    $CloudBlockBlob = [Microsoft.Azure.Storage.Blob.CloudBlockBlob] $blob.ICloudBlob
    $CloudBlockBlob.Properties.ContentType = <Desired type as string>
    $CloudBlockBlob.SetProperties()
}

注意:对于 Azure 文件存储,您可能希望将库更改为 [Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob]

于 2021-06-25T22:15:05.840 回答