もともとこのようなことを行う必要性が生まれたのは、
Office2007以降の形式(.xlsx, .docx, .pptx)のファイルをブラウザからS3にアップした際に、
Content-Typeの自動設定が行われると、
「application/vnd.ms-excel」(Excelの場合)
と設定されます。
これはOffice2003以前の形式(.xls, .doc, .ppt)のContent-Typeであるため、
ブラウザで対象ファイルをダウンロードすると、
「.xlsx」だったファイルの拡張子が、「.xls」となってダウンロードされてしまうという事象が起こるのです。(Excelの場合)
これを防ぐためにLambdaを利用してContent-Typeを変更してしまおうということで、以下コード。
console.log('Loading event');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
var s3tokyo = new aws.S3({apiVersion: '2006-03-01', endpoint: 'https://s3-ap-northeast-1.amazonaws.com'});
exports.handler = function(event, context) {
console.log('Received event:');
console.log(JSON.stringify(event, null, ' '));
// Get the object from the event and show its content type
var bucket = event.Records[0].s3.bucket.name;
var key = decodeURIComponent(event.Records[0].s3.object.key);
s3tokyo.getObject({Bucket:bucket, Key:key},
function(err,data) {
if (err) {
console.log('error getting object ' + key + ' from bucket ' + bucket );
context.done('error','error getting file' + String(err));
}
else {
console.log('logging Content-Type : ',data.ContentType);
if ((data.ContentType != "application/vnd.ms-excel")&&
(data.ContentType != "application/msword")&&
(data.ContentType != "application/vnd.ms-powerpoint")){
console.log('Content Type not MS-Office file.');
context.done(null,'skip execution.');
}
else {
var type = "binary/octet-stream";
var params = {
Bucket: bucket,
CopySource: bucket + "/" + encodeURIComponent(key),
Key: key,
ContentType: type,
MetadataDirective: "REPLACE"
};
console.log('replace object.');
console.log('bucket : ' + bucket);
console.log('CopySource : ' + bucket + "/" + key);
s3tokyo.copyObject(params, function(err2, data2){
if (err2){
context.done('error','error2 getting file '+ String(err2));
}else{
console.log('replace done! Content-Type : ',data2.ContentType);
context.done(null,'object meta-data changed.');
}
});
}
}
}
);
};
#マルチバイト文字のKey名への対応#
2バイト文字のファイル名の場合にうまくいかなかったのですが、
S3内ではURIエンコードされているので、
getObjectの際はdecodeURIComponent(key)
putObjectの際はencodeURIComponent(key)
することで解決できます。
#イベントソースの設定#
以下2つのイベントを対象バケットに設定します。
・ Put
・ CompleteMultiPartUpload
AWSマネージメントコンソール、API、CLIいずれによっても、ファイルサイズによってMultiPart Uploadに自動的に切り替わりますので、CompleteMultiPartUploadも有効にしておくことが必要です。
※Copyイベントの設定は厳禁です。これを設定すると、コード内でのCopy処理によってループしてしまうかも。