1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Blob StorageにPDFをアップロードしたらContentTypeを確認しよう【自戒記事】

Last updated at Posted at 2025-06-16

先に結論

  • Azure SDK を用いてPDFファイルをアップロードした場合、ContentTypeのデフォルト値はapplication/octet-streamになる模様
  • ContentTypeがapplication/octet-streamのBlobの場合、WEBブラウザから当該BlobのURLにアクセスすると、プレビューではなくファイルダウンロードに遷移してしまう
    • ContentTypeをapplication/pdfに変えればプレビュー可能
    • この差分は、ブラウザ側で参照データのContentTypeを元に振る舞いを制御していることに起因する
  • @azure/storage-blobなどのAzure Storage クライアントライブラリを用いてファイルをアップロードしている場合、Blobアップロード関数のOptionで blobHTTPHeadersblobContentTypeを設定することで任意のContentTypeを指定できる

検証条件

  • 言語:TypeScript
  • ランタイム:Node.js
  • Azure Storageクライアントライブラリ:@azure/storage-blob

やりたいこと

  1. WEBアプリからPDFファイルをBlob Storageにアップロードしたい
  2. アップロードしたPDFファイルのURLを取得し、WEBアプリの任意のボタンを押すと当該ファイルをWEBブラウザ上で開くようにしたい

やったこと:PDFファイルのアップロード(修正前)

上記のMS Learnを参考に、BlockBlobClientを生成し、uploadStream関数を用いてPDFファイル(Readableストリームに変換済み)をBlob Storageにアップロードする。

.ts
const uploadDataAsPdf: (data: File) => Promise<void> = async (data) => {
  /** アップロード先 Azure Blob Storage コンテナ名 */
  const containerName = "upload-test";
  /** アップロードするPDFファイル名 */
  const blobName = "upload-test.pdf";

  // File型の data をストリームに変換
  const fileStream = data.stream();
  const reader = fileStream.getReader();
  /** アップロードするPDFファイルデータ */
  const targetData: Readable = new Readable({
    async read() {
      const result = await reader.read();
      if (result.done) {
        this.push(null);
      } else {
        this.push(Buffer.from(result.value));
      }
    },
  });
  
  /** アップロード先 Azure Blob Storage の接続文字列 */
  const clientUrl = 'hogehogehogehoge';
  /** 
   * Blob サービスクライアントを作成
   * @see https://learn.microsoft.com/ja-jp/javascript/api/overview/azure/storage-blob-readme?view=azure-node-latest#using-connection-string
   */
  const blobServiceClient = BlobServiceClient.fromConnectionString(clientUrl);
  /** コンテナクライアントインスタンス */
  const containerClient = blobServiceClient.getContainerClient(containerName);
  /** Block Blobクライアント */
  const blockBlobClient = containerClient.getBlockBlobClient(blobName);
  // Blob StorageにPDFファイル(Readbaleストリーム)をアップロード
  await blockBlobClient.uploadStream(stream);
}

この関数を用いて、リクエストボディで受け取ったFileデータをAzure Blob StorageにアップロードするPOST APIを作成。
お試ししてみると……


image.png
アップロードに成功した!

image.png
プレビューも確認したが、問題なさそうだ!

ということでやりたいこと1「WEBアプリからPDFファイルをBlob Storageにアップロードしたい」はクリアー。

ではアップロードしたPDFファイルのURLにブラウザからアクセスしてみよう!


image.png

ダウンロードポップアップが開いた?????

やりたいこと2は「アップロードしたPDFファイルのURLを取得し、WEBアプリの任意のボタンを押すと当該ファイルをWEBブラウザ上で開く」。このままではWEBブラウザ上でのプレビューが実現できない!

よわよわエンジニア、ContentType(MIMEタイプ)を知る

よわよわエンジニアがあれこれネットの海に問い合わせたところ、どうやらブラウザでPDFをプレビューするにはContentTypeをapplication/pdfにする必要があるっぽいことを発見。

ContentTypeは、ファイルやインターネット上で転送されるデータの形式を識別するためのコード。
MIMEタイプとも表記される。
よくAPIレスポンスなどで目にする text/plainapplication/jsonimage/jpegなどもContentTypeの一種。

今回はFile(=バイナリデータ)をアップロードしたが、この場合のContentTypeのデフォルト値はapplication/octet-streamになる模様。拡張子で言うと.binが相当。任意の種類のバイナリーデータならなんでもapplication/octet-stream

image.png

↑たしかに upload-test.pdf のContentTypeはapplication/octet-streamである……。

そして、「ダウンロードポップアップの表示」は、参照したデータのContentTypeがapplication/octet-streamの場合のブラウザ側の挙動だった。

もしデータのContentTypeがapplication/pdfになっていると、ブラウザ側がPDFファイルに対するデフォルトの振る舞いをしてくれる。それが今回の期待値である「PDFのブラウザ上でのプレビュー」だったというわけである。

やったこと:PDFファイルのアップロード(修正後)

ということで、Blobストレージにアップロードする際、明示的に「このBlobはPDFなんですよ!」と示してあげれば良いと判明。

今回用いていた Azure Storageクライアントライブラリ@azure/storage-blobuploadStream関数のリファレンスを確認する。

image.png

第4引数optionsに指定するBlockBlobUploadStreamOptionsの詳細を確認すると、この中にblobHTTPHeadersという、blobContentTypeとやらを設定するプロパティがあることがわかる。

image.png
image.png

ということで、先ほどのソースのうちuploadStream関数を呼び出していた部分を以下の通り修正。

// Blob StorageにPDFファイル(Readbaleストリーム)をアップロード
- await blockBlobClient.uploadStream(stream);
+ await blockBlobClient.uploadStream(
+   stream,
+   undefined, // bufferSize :デフォルト値「8」を使用
+   undefined, // maxConcurrency :デフォルト値「5」を使用
+   {
+     blobHTTPHeaders: { blobContentType: "application/pdf" }, // PDFとしてアップロード
+   },
+ );

これで再度試してみると……

image.png

↑ upload-test.pdf のContentTypeがapplication/pdfになっている!

image.png

↑ URLにアクセスすると、ちゃんとPDFをプレビューできている!

結論

Azure Blob StorageのようなBlobサービスを用いる際は、当該サービスの概念(コンテナとか仮想ディレクトリとか)を押さえることも、Azure SDKを使えることも大事であるが、
まずは扱うデータの特性や仕様自体をちゃんと押さえる必要がある(当たり前体操)

動いたやったね!!! で終わらず、「で、私いまPDFファイルを何をどうしてStorageにアップロードできたの??? FileってなにBlobってなに???」……など自分が書いたコード/実施した操作の内容をちゃんと把握しよう。。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?