S3にデプロイしたVue.jsでpublicに配置したPDFを参照したら文字化けしてた
問題の概要
S3にデプロイしたVue.jsアプリケーションで、publicフォルダに配置したPDFファイルを参照した際に文字化けが発生する問題が起きました。
原因
この問題の主な原因は、S3のContent-Typeが正しく設定されていないことです。PDFファイルがtext/plainなど誤ったMIMEタイプで配信されると、ブラウザが正しく解釈できず文字化けが発生します。
解決方法
1. S3のContent-Typeを修正
S3コンソールまたはAWS CLIを使用して、PDFファイルのメタデータを修正します。
aws s3 cp s3://your-bucket/path/to/file.pdf s3://your-bucket/path/to/file.pdf \
--metadata-directive REPLACE \
--content-type application/pdf \
--acl public-read2. デプロイ時にContent-Typeを指定
Vue.jsのビルド設定やデプロイスクリプトで、PDFファイルのContent-Typeを明示的に指定します。
// vue.config.js または デプロイスクリプト
const mime = require('mime-types');
// S3アップロード時の設定例
{
ContentType: mime.lookup('file.pdf') || 'application/pdf'
}3. CloudFrontを使用している場合
CloudFrontのキャッシュを無効化して、新しいContent-Typeが反映されるようにします。
aws cloudfront create-invalidation \
--distribution-id YOUR_DISTRIBUTION_ID \
--paths "/path/to/file.pdf"予防策
参考
PDFの正しいMIMEタイプはapplication/pdfです。その他のファイルタイプについても、適切なContent-Typeを設定することで同様の問題を回避できます。
AWS CDKでの解決方法
はい、AWS CDKで実装している場合、cdk.pyでS3バケットのデプロイ設定を見直すことで解決できます。
BucketDeploymentでContent-Typeを指定
AWS CDKのs3_deployment.BucketDeploymentを使用している場合、content_typeパラメータを設定することで、ファイルごとに適切なMIMEタイプを指定できます。
from aws_cdk import (
aws_s3 as s3,
aws_s3_deployment as s3_deployment,
Stack
)
class MyStack(Stack):
def __init__(self, scope, id, **kwargs):
super().__init__(scope, id, **kwargs)
bucket = s3.Bucket(self, "MyBucket",
website_index_document="index.html",
public_read_access=True
)
# デプロイ時にContent-Typeを指定
s3_deployment.BucketDeployment(self, "DeployWebsite",
sources=[s3_deployment.Source.asset("./dist")],
destination_bucket=bucket,
content_type="application/pdf", # PDFファイル用
exclude=["*.html", "*.js", "*.css"], # PDF以外を除外
)
# HTML/JS/CSS用の別のデプロイメント
s3_deployment.BucketDeployment(self, "DeployOtherAssets",
sources=[s3_deployment.Source.asset("./dist")],
destination_bucket=bucket,
exclude=["*.pdf"], # PDFを除外
)より柔軟な設定方法
複数のファイルタイプを扱う場合は、cache_controlと組み合わせて設定することもできます。
s3_deployment.BucketDeployment(self, "DeployWithMetadata",
sources=[s3_deployment.Source.asset("./dist")],
destination_bucket=bucket,
metadata={
"Content-Type": "application/pdf"
},
cache_control=[
s3_deployment.CacheControl.max_age(Duration.days(365))
]
)確認ポイント
この方法で、CDKのコードレベルでContent-Typeの問題を解決できます。