safariにおいて、ダウンロードしたPDFの別タブ表示ができない

事象

APIでレスポンスされたPDFファイルをブラウザで別タブ表示を行おうとしています。
ChromeやFireFoxでは問題なく動作したのですが、Macのsafariで実行すると、うまく表示がされません。
具体的にはURL.createObjectURLで生成したURLが、別タブで開いた際にドメイン部がnullになってしまっており、URLが正しく解釈されていないように見えます。
(下図参照)
知見をお持ちの方がいらっしゃればご教示お願い致します。

実際の実装

  private openFile(file: Blob, fileName: string): void {
    const blob: Blob = new Blob([file], { type: file.type });
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
      // IEの場合
      window.navigator.msSaveOrOpenBlob(blob, fileName);
    } else {
      // IE以外の場合
      const anchor: HTMLElementTagNameMap["a"] = document.createElement("a");
      document.body.appendChild(anchor);
      anchor.href = window.URL.createObjectURL(blob);
      anchor.target = "_blank";
      anchor.click();
      anchor.remove();
    }
  }

環境

Angular 10
macOS Catalina 10.15.7
Safari 14.0

1 Likes

AnchorElement のClickの代わりに、window.open を利用すると動作するはずです。

1 Likes

nomeaning777さん
window.openに変えましたが、ポップアップブロックにより表示が阻まれ、それを許可しても事象欄の画像のようにドメイン部がnullになり正しく開かれませんでした。
ご提示いただいたソースコードは別タブで正しく開いたので、原因を調べてみたところ以下ポップアップブロックの仕様によるものでした。
1.ユーザーアクション(ボタンクリック等)によるポップアップ表示であればブロックされない。
2.ユーザーアクションとwindow.openの間にサーバ通信が発生すると、ポップアップブロックされる。

ご参考リンク

ありがとうございます。SafariではポップアップブロックがHTMLAnchorElementとwindow.open で異なる挙動を示すのですね…。

_blank をtargetにした場合のみドメイン部がnullになり動作しないようなので、
適当な文字列に変更すれば動作しました。
https://typescript-5bertz.stackblitz.io/

ただし、他のブラウザがそうであるように、
window.openがブロックされる状況ならば、HTMLAnchorElementのclickでも同様にブロックされるのが正しいと考えられるので、
個人的にはこの挙動に頼るならば、動かなくなることを前提にした方が良いのかなとは思います。

参考: https://stackoverflow.com/a/53338518

1 Likes

ご提示いただいたソースコードのように、targetを適当な文字列にしたところ解消しました。
現状他に有効な手段もないので、こちらの対応で進めるか、別タブ表示を諦めdownload属性付きaタグによるダウンロードに変更するかの2択を考えています。
こちらの対応は仰る通り、将来的に動かなくなる可能性もあるので、それも踏まえ検討したいと思います。

色々とご意見ありがとうございました。
勉強になりました。