Google Apps Scriptでmultipart/form-data形式のhttpリクエストの受信処理をするには?

2,702 views
Skip to first unread message

Tsuyoshi KUSAKA

unread,
Apr 10, 2012, 7:49:15 AM4/10/12
to Google Apps API Japan
日下と申します。
初めて投稿させていただきます。よろしくお願い致します。
もしこちらに投稿すべきでない内容でしたら、お手数ですがご指摘いただけたらと思います。

Google Apps Scriptでhttpリクエストを受信して処理するプログラムを作成しております。

そのプログラムの中で、multipart/form-data形式で送られてきたファイルのファイル名を取得したいのですが、
以下のようなロジックで確認したところ、e.parameters の中にはファイルをセットしたリクエストパラメータ名が含まれていませんでした。


function doPost(e) {

for (var p in e.parameters) {
Logger.log("param:" + p + ":" + e.parameter[p]);
//各リクエストパラメータごとの処理(Google Spreadsheetにデータを貼りつけるなど)
}

}


パラメータ e がどのようなオブジェクトであるか、ドキュメントを探してもみましたが、見つけることができませんでした。

multipart/form-data形式で送られてきたデータについてはどのように処理すればよいか、
(multipart/form-data形式で送られてきたファイルのファイル名はどのように取得できるか)
ご教示いただきたく考えております。

どうぞよろしくお願い致します。

soundTricker

unread,
Apr 10, 2012, 8:35:27 AM4/10/12
to google-app...@googlegroups.com
こんばんは、大橋(soundTricker)です。

ちょっと贈り側(doGet側)のコードが不明なのでなんとも言えませんが、
以下のようなコードで取得できるはずです。

以下のコードはGoogle Apps Scriptの公式ドキュメントから持ってきてます。


 function doGet(e) {

 var app = UiApp.createApplication().setTitle("Upload CSV to Sheet");
   var formContent = app.createVerticalPanel();
   formContent.add(app.createFileUpload().setName('thefile'));
   formContent.add(app.createSubmitButton());
   var form = app.createFormPanel();
   form.add(formContent);
   app.add(form);
   return app;
 }

 function doPost(e) {
   var fileBlob = e.parameter.thefile;
   var doc = DocsList.createFile(fileBlob);
   
   Logger.log(doc.getName());
   Logger.log(doc.getContentAsString());
 }
 
GUI Builderで画面をつくっている場合は、イベントのコールバックエレメントを設定していない可能性があります。
ちょっと画面キャプチャが今取れないので、わからない場合は返信しておいてください~
明日辺りキャプチャ取って貼り付けます。

soundTricker

unread,
Apr 10, 2012, 9:01:23 AM4/10/12
to google-app...@googlegroups.com
大橋(soundTricker)です。

申し訳ないです。さすがに解説なさすぎでした。
コードにコメント追加してみました。


 function doGet(e) {

   var app = UiApp.createApplication().setTitle("Upload CSV to Sheet");

   //formに積める垂直方向パネルを作成
   var formContent = app.createVerticalPanel(); 
   
   //FileUploadを作成し、パラメータ名をthefileに設定 パネルに追加
   formContent.add(app.createFileUpload().setName('thefile'));

   //サブミットボタンを追加
   formContent.add(app.createSubmitButton());

   //フォームパネルを作成
   var form = app.createFormPanel();

   //追加
   form.add(formContent);
   app.add(form);
   return app;
 }

 function doPost(e) {
   //FileUpload.setName で設定した名前でパラメータがくる パラメータはblobです。
   var fileBlob = e.parameter.thefile;

   //DocsListを利用して、blobからFileオブジェクトを作成
   var doc = DocsList.createFile(fileBlob);
   
   Logger.log(doc.getName()); //ファイル名
   Logger.log(doc.getContentAsString()); //内容
 }

です。

先程書いてあった、イベントコールバック云々は私の間違えなので忘れてください。
doPostの場合は不要なはずです。

 

大橋啓介

unread,
Apr 10, 2012, 10:51:11 AM4/10/12
to google-app...@googlegroups.com
再三の返信申し訳ないです。。。
大橋(soundTricker)です。

ちょっと気になったので色々試しました。

1.記載されているコードについて
e変数には通常e.parameterにformから渡されたパラメータが入ります。
今記載されているe.parametersはformにて同名のパラメータが渡された場合に入るはずです。

またパラメータを調べたい場合はLogger.log(e)で渡した値がJSON.stringifyされるので、
そのまま渡しても大丈夫なはずです。

2.僕が記載したコードについて

DocList.createFileを利用していましたが、これだとGoogle Docsにファイルができてしまいました。。。
僕のコードで言うとe.parameter.thefileパラメータ(FileUploadで渡される値)はBlobオブジェクトですので
e.parameter.thefile.getName()でファイル名を取得できます。


ほかなにか質問があれば返信してください。

Tsuyoshi KUSAKA

unread,
Apr 11, 2012, 7:02:39 AM4/11/12
to Google Apps API Japan
大橋様

日下です。

早速ご返信いただき、ありがとうございます。


まず、送信側について記述ができておらず、申し訳ございませんでした。
送信側は自社開発したWebシステムを使っております。

 Webシステムからhttpリクエストでデータを送信
 →Google Apps Script経由で、Google Spreadsheetにデータを貼りつける

といったことを実現しようとしております。


> またパラメータを調べたい場合はLogger.log(e)で渡した値がJSON.stringifyされるので、
> そのまま渡しても大丈夫なはずです。
ということでしたので、
Logger.log(e)で出力させてみたのですが、
ファイルをセットしているはずのリクエストパラメータについて情報が出力されませんでした。

ただ、ファイル添付がある場合とない場合とでは、Logger.log(e)で出力された中の
 contentLength
の値が大きく違っておりましたので、データとしては渡っているのではないかと考えております。
#またGoogle Apps Scriptではなく、
 別のGoogle App Engine(Python)で作られたhttpリクエスト受信&表示プログラムがあるのですが、
 そちらでもファイル名の取得はできていましたので、おそらく送信は問題ないかと考えております。

Logger.log(e)の出力でファイルをセットしているパラメータの情報が出力されない以上は
eからは取り出せないと考えるべきかと思うのですが、
eから取得できないhttpリクエストに関するデータを取得する方法はないものなのでしょうか?
#例えば、今回の話とは別の話になりますが、
 httpリクエストヘッダの情報を取り出したいような場合も、eからは処理できないはずですので
 別の手段があるのではないかと考えております。

たびたびで申し訳ございませんが、ご教示よろしくお願い致します。

soundTricker

unread,
Apr 11, 2012, 7:34:39 AM4/11/12
to google-app...@googlegroups.com
日下さん

こんばんは。大橋(soundTricker)です。
なるほど送信側はGASではないんですね。

まずファイルアップロードに関しての話ですが、
いくつか試したところ、gasのdoPostメソッドに大してファイルアップロード(というよりパラメータを渡す)には、
doGetと同じURLではダメなようです。

以前書いているコードをサービスとして実行し(doGet側)、formタグのaction属性を診てもらうとわかるのですが、
多分userAppPost?lib={なんかのkey}というところに投げていると思います。

僕の方でローカルにhtmlファイルを作成し、実験してみたところ、
通常doGetメソッドにアクセスするURL(gasエディタ上にて表示されるURL)のexec以降(execを含む)を削除し、
上のuserAppPostにformのactionを変更してみたところうまくいきました。
多分gasのexecというURLではrequest bodyの中まで見ないんでしょうね。

ただし上記の方法は、正規にgoogle apps scriptのドキュメントに書いてある方法では無いので、
常にちゃんと動くかはちょっと保証できないです。。。(このKeyっぽいのがいつ変わるか、固定なのかも不明なので)申し訳ないです。。。

またhttpのリクエストヘッダーに関してはちょっと僕はわかりません。。。
doGetやdoPostが起動した時の、
thisオブジェクトの中を全部出してみたりしましたが見つからなかったので、
今のところは取得方法は無いのかもしれません。


Tsuyoshi KUSAKA

unread,
Apr 12, 2012, 9:05:34 AM4/12/12
to Google Apps API Japan
大橋様

日下です。

今回も早急にご返信をいただいており、ありがとうございます。
またいろいろお試しいただき、ありがとうございます。

GASで作成した処理をサービスとして公開した場合に
 https://docs.google.com/macros/exec
以外のURLでもアクセスができるんですね。
ただ、GASのドキュメントにない非公式な方法ということですので、採用しづらいというのが正直なところにはなります。

少なくとも現時点でexecの方のURLでは処理できないということが明確にはなりましたので、大変助かりました。
それを前提にどうすべきかを考えることにします。

いろいろありがとうございました。

大橋啓介

unread,
Apr 12, 2012, 10:48:22 AM4/12/12
to google-app...@googlegroups.com

いえいえ
こちらこそ完全な解決が出来ず申し訳ないです。

一応もう検討されているかもしれませんが別の提案だけ書いておきますと、
サーバサイドがどこかで持てているのであれば書いてある事はGData API(Spreadsheet API)でもやれることかな?っと思いますので
そちらもご検討をして頂くといいかもしれません。
(もともとgasも多分裏はgdata使ってる気がしますし)

このコミュニティは確かgdata apiも対象の範囲ですので
また何かありましたら質問をポストして見て頂くと誰かが答えてくれていいかも知れませんよ!

大橋啓介

unread,
Apr 12, 2012, 10:58:42 AM4/12/12
to google-app...@googlegroups.com

P.S.
特に誰あてでも無くURLの話が出たのでTips程度の話ですが、
gasでサービスを作った場合、
https://docs.google.com/macros/execだけでなく
exec以降が同じであればhttps://sites.google.com/macros/execのドメインでも動くはずです(確認はappsでしかしてません)

Spreadsheet側でサービスを作ってsites側に埋め込みたい場合urlを上のように変えないと以前は埋め込みが確か出来なかったので覚えておくと得かもです。

ただしドキュメントに書いてあるかは分からないです、、

Tsuyoshi KUSAKA

unread,
Apr 13, 2012, 12:23:37 PM4/13/12
to Google Apps API Japan
大橋様

日下です。

追加情報ありがとうございます。

送信側システムが既存で持っているREST APIでhttpリクエストを送信していることもあり、
受信側で解決したいと考えていました。

GASで処理するかわりに、
 Spreadsheet API経由でデータを貼り付けするサーバアプリを立てる
という方法でも実現は可能ということですね。
#もし対象のSpreadsheetが多くなった場合には、その方が個々のSpreadsheetにGASを仕込むより効率的ですね

ただ状況的にはあまり時間をかけられないこともあり、悩ましいところです。

藤田悠平

unread,
Jan 13, 2015, 3:06:33 PM1/13/15
to google-app...@googlegroups.com
現在、Googleドライブに外部からファイルをアップしてもらう際に、アカウントを持っていなくてもファイルをアップできるようにアップローダーを作成しています。
その時に、諸事情でファイル名を変更する必要があります。
getName()でファイル名を取得するのはいいのですが、拡張子を除いたファイル名を取得する方法はないでしょうか?

2012年4月10日火曜日 23時51分11秒 UTC+9 soundTricker:
Reply all
Reply to author
Forward
0 new messages