web-dev-qa-db-ja.com

Chromeに表示されるPDFオブジェクトのファイル名を設定できますか?

VueアプリでPDFブロブとして受け取り、ブラウザのPDFビューアーを使用して表示したい。

ファイルに変換し、オブジェクトのURLを生成します。

const blobFile = new File([blob], `my-file-name.pdf`, { type: 'application/pdf' })
this.invoiceUrl = window.URL.createObjectURL(blobFile)

次に、そのURLをオブジェクト要素のdata属性として設定して表示します。

<object
  :data="invoiceUrl"
  type="application/pdf"
  width="100%"
  style="height: 100vh;">
</object>

ブラウザは、PDFビューアを使用してPDFを表示します。ただし、Chromeでは、提供するファイル名(ここではmy-file-name.pdf )は使用されません:PDFビューアーのタイトルバーにハッシュが表示され、「右クリック->名前を付けて保存...」またはビューアーのコントロールを使用してファイルをダウンロードすると、blobのハッシュ(cda675a6-10af-42f3-aa68-8795aa8c377d または類似)。

ビューアとファイル名は、Firefoxで期待したとおりに機能します。ファイル名が使用されていないのはChromeのみです。

ネイティブJavascript(ES6を含むが、Vue以外のサードパーティの依存関係はない)を使用して、Chromeのblob/object要素のファイル名を設定する方法はありますか?

[編集]役立つ場合、応答には次の関連ヘッダーがあります。

Content-Type: application/pdf; charset=utf-8
Transfer-Encoding: chunked
Content-Disposition: attachment; filename*=utf-8''Invoice%2016246.pdf;
Content-Description: File Transfer
Content-Encoding: gzip
8
false_azure

Chromeの拡張機能は、URIに設定されているリソース名、つまりfile.ext in protocol://domain/path/file.ext

したがって、元のURIにそのファイル名が含まれている場合、最も簡単なのは、Blobの方法ではなく、PDFを直接取得したURIに<object>のdataを作成することです。

今、それを行うことができない場合があり、これらのために、複雑な方法があります。これは、将来のChromeのバージョンでは動作しない可能性があり、おそらく他のブラウザでは動作しません Service Worker を設定する必要があります。

最初に言ったように、Chromeはファイル名を検索してURIを解析します。そのため、BlobURIを指すこのファイル名を持つURIを作成する必要があります。

そしてそれを可能にするために、私が今のところ見つけた唯一の方法は、

  1. ドキュメントから、POSTリクエストを作成します。これにより、ServiceWorkerにBlobが送信されます。
  2. ServiceWorkerから、送信されたBlobをキャッシュします
  3. それでもServiceWorkerから、新しい偽のURIを返します。これは、2。にキャッシュされたBlobでマップします
  4. ドキュメントから、<iframe>のsrcを設定します1 その偽のURIに。
  5. ServiceWorkerからリクエストをキャッチし、代わりにキャッシュされたBlobを送信します。
  6. ドキュメントから、お楽しみください。

1。Chromeの<object>タグから行われたリクエストを確認できなかったため、ここでiframeを使用することをお勧めします(IEでも良い結果が得られます) 。

またはコードで、

document.html

// register our ServiceWorker
navigator.serviceWorker.register('/sw.js')
   .then(...
...

function displayRenamedPDF(file, filename) {
  // we use an hard-coded fake path
  // that we will check in every requests from the SW
  const reg_path = '/nameForcer_register/'
  // pass the filename
  const url = reg_path + encodeURIComponent(filename);
  const xhr = new XMLHttpRequest();
  xhr.open('POST', url);
  return new Promise((res, rej) => {
    xhr.onload = e => {
        const frame = document.createElement('iframe');
        frame.src = xhr.response;
        document.body.append(frame);
        return frame;
    };
    xhr.send(file);
  })
}

ServiceWorkerでsw.js

self.addEventListener('fetch', function(event) {
  const req = event.request,
    url = new URL(req.url),
    // parse the /path/ from every request url
    pathes = url.pathname.split('/'),
    // are we registering
    nameRegIndex = pathes.indexOf('nameForcer_register'),
    // or fetching
    nameFetcherIndex = pathes.indexOf('nameForcer_fetch');

  if(nameRegIndex > -1) { // register
    event.respondWith(
      req.blob() // grab the POSTed Blob
        .then((blob) => {
          const filename = pathes[nameRegIndex+1] || '';
          // store in our db object
          db[filename] = blob;
          return filename;
        })
        .then((filename) =>
          new Response('/nameForcer_fetch/' + filename)
        )
    );
  }
  else if(nameFetcherIndex > -1) { // fetch
    const filename = pathes[nameFetcherIndex + 1];
    const cached = db[filename];
    // just for Firefox, Chrome doesn't care...
    const headers = new Headers({
      'Content-Disposition': 'inline; filename="' + decodeURIComponent(filename) + '"'
    });
    event.respondWith(
      new Response(cached, {
        headers: headers
      })
    );
    delete db[filename];     // !! one time URI !!
  }
  else { // normal requests
    event.respondWith(fetch(event.request))
  }
});

残念ながら、plnkr.coでServiceWorkerを動作させることはできませんでしたが、ローカルホストにコピーできるはずの ここにセットアップ 全体を見つけることができます。


また、他の解決策として、自分で確認するのに時間をかけなかったので、独自のpdfビューアーを実行することになるでしょう。

Mozillaはjsベースのプラグイン pdf.js を利用可能にしているので、そこからファイル名を設定できるはずです(もう一度掘り下げていませんが)。


最後に、FirefoxはblobURIが指すnameオブジェクトのFileプロパティを使用できます。だから、それはOPが要求したものではありませんが、FFでそれが必要なのは

const file = new File([blob], filename);
const url = new URL(blob);
object.data = url;
4
Kaiido

独自のサーバー経由でリソースをリクエストしている場合は、Content-Disposition応答でファイル名を渡す応答ヘッダー。

Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"

ファイル名と拡張子に置き換えることができます。あなたはこれを見ることができます link .

0
Pranay Tripathi

Chromeでは、ファイル名はURLから取得されるため、blob URLを使用している限り、短い答えは「いいえ、Chromeに表示されるPDFオブジェクトのファイル名を設定できません」です。 blob URLに割り当てられたUUIDを制御することはできず、object要素を使用してページの名前としてそれをオーバーライドする方法もありません。 PDF内でタイトルが指定され、PDFビューアーにドキュメント名として表示される可能性がありますが、ダウンロード時にハッシュ名が取得されます。

これはセキュリティ上の予防策のように見えますが、確実に言うことはできません。

もちろん、URLを制御できる場合は、URLを変更してPDFファイル名を簡単に設定できます。

0
Old Pro