質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

2回答

2528閲覧

JavaScript Blob変換でPDFファイル名が変になる

JanTh1989

総合スコア87

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2024/01/22 06:11

編集2024/01/22 06:43

実現したいこと

JavaScriptを起点として、PHP、APIを経由してのPDFファイルのダウンロード(別タブ表示)。
流れ

  1. JavaScriptがAjaxでPHPにアクセス
  2. PHPが別サーバAPIにアクセスしてPDFファイル取得
  3. PHPはバイナリをbase64エンコードしてJsonでJavaScriptに返す
  4. JavaScriptは取得したbase64をBlob変換して表示

発生している問題・分からないこと

PDFの表示までは行えているのですが、ファイル名が想定のものにならず変な形になります。
例)
想定:012345.pdf
結果:1d098396-c899-42a1-9c87-5824ba992a9b
※結果はファイル名が固定でも毎回値が変わってきます。

Blob変換方法の誤りなどあるのかもしれませんが、何が悪いのかが判断できずにいます。
ご教授お願いいたします。

該当のソースコード

JavaScript

1function downloadPdf(obj) { 2 let ua = getMobileOS(); 3 if(ua !== "Android" && ua !== "Other"){ 4 windowReference = window.open(); 5 } 6 let sendData = {'key_number' : obj.getAttribute('data-value')}; 7 $.ajax({ 8 type: "POST", 9 url: "phpパス", // POST先のURL 10 data: sendData 11 }) 12 .done(function(res) { 13 let json = JSON.parse(res); // ファイル名とbase64をphpから取得 14 const fileName = json['fileName']; 15 const pdf = json['pdf']; 16 17 let mime_ctype = "application/pdf"; 18 let file = toBlob(pdf, mime_ctype); 19 20 let url = URL.createObjectURL(blob); 21 22 if(ua !== "Android" && ua !== "Other"){ 23 windowReference.location = url; 24 }else{ 25 window.open(url, '_blank'); 26 } 27 }) 28 .fail(function(jqXHR, status, err) { 29 console.log(status, err); 30 }); 31} 32 33function toBlob(base64, mime_ctype) { 34 let bin = atob(base64.replace(/^.*,/, '')); 35 let buffer = new Uint8Array(bin.length); 36 var bom = new Uint8Array([0xEF, 0xBB, 0xBF]); 37 38 for (let i = 0; i < bin.length; i++) { 39 buffer[i] = bin.charCodeAt(i); 40 } 41 let blob; 42 // Blobを作成 43 try { 44 blob = new Blob([bom, buffer.buffer], { 45 type: mime_ctype, 46 }); 47 } catch (e) { 48 return false; 49 } 50 return blob; 51} 52 53function getMobileOS(){ 54//iPhoneの場合 55 if(navigator.userAgent.indexOf('iPhone') > 0){ 56 //iPhone用の処理 57 return "iPhone"; 58//iPadの場合 59 }else if(navigator.userAgent.indexOf('iPad') > 0){ 60 //iPad用の処理 61 return "iPad"; 62//iPodの場合 63 }else if(navigator.userAgent.indexOf('iPod') > 0){ 64 //iPod用の処理 65 return "iPod"; 66//Androidの場合 67 }else if(navigator.userAgent.indexOf('Android') > 0){ 68 //Android用の処理 69 return "Android"; 70 } 71 72 return "Other"; 73}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

・aタグ作成してdownloadにファイル名設定とtargetに_blank設定でファイル指定、別タブ表示する方法は認識しております。
ただ、Mac Chromeではダウンロードのみで別タブ表示されない。
iPhone Safariで動いてくれないなどあったため、このaタグをやめました。
・toBlob関数では当初BOMを入れていなかったため、念の為new BlobにBOMを追加
・Blob→File→Blobとファイル名指定できるFileオブジェクトに変換をしてBlobに戻してみましたが、結果は同じでした。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

結果:1d098396-c899-42a1-9c87-5824ba992a9b

URL.createObjectURL() で作成した URL は末尾がそのようなものになります。このURLを変更する手段は存在しないと思います。クライアント側で唯一できることは <a download=...> でダウンロード時のファイル名を指定することです。

クライアントに base64 されたデータを送ってからデコードしてダウンロードさせるという構成が奇妙に感じます。サーバから生のデータと Content-Disposition ヘッダを返すのが素直な設計かと。

投稿2024/01/22 07:46

int32_t

総合スコア21927

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ソースの意図がよくわかりませんが、ajaxでおくってPHPでそのまま出力してダウンロード処理をしたいということですか?ダウンロードさせるならajaxではなく普通にサブミットしないとおかしくないですか?

# 確認
まずはこれでダウンロードできるかどうか確認してください

HTML

1<a href="data:image/gif;base64,R0lGODdhEAAQAIACAAUFBfr6+iwAAAAAEAAQAAACJoyPqcsIrV6QE1hbscSGzl4dXJiJ1HM66ua1nPclG9ixNgzl+s4XADs=" download="test.gif">test.gif</a>

これでダウンロードできないならXHRでのダウンロードはむずかしいです
PHPで文字列化して取得してバイナリで表示するくらいなら最初からPHPの結果をhttpヘッダをつけて呼び出せばダウンロードされるんですけどね

投稿2024/01/22 07:01

編集2024/01/22 10:06
yambejp

総合スコア117650

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

JanTh1989

2024/01/22 07:39

実現したいことに記載した以下が目的になります。 「JavaScriptを起点として、PHP、APIを経由してのPDFファイルのダウンロード」 「ダウンロードさせるならajaxではなく普通にサブミットしないとおかしくないですか?」 ここの意図を汲み取れず申し訳ありません。 方法が根本的に間違っているということでしょうか?
yambejp

2024/01/22 08:01

仮にPHPでダウンロード画面をだすなら multipart/form-dataなformでファイルをsubmitすることにより戻りがダウンロードとして取得できるということです、ajaxでおくる必要はありません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問