C# で ChatWorkにエクセルファイルをアップロードしたく下記のコードを実行しましたら
ファイルのアップロードには成功するのですが、ファイルが壊れてしまいます。
※一応ここにそうように作成しました。
http://developer.chatwork.com/ja/endpoint_rooms.html#POST-rooms-room_id-files
どなたか、ご教授いただきたく何卒よろしくお願いいたします。
※Zuishin様のご指導のもと、このコードでエクセルもいけました!
static void Main(string[] args) { FileSendExe(); } static void FileSendExe() { // テストファイル string filePath = @"デスクトップ\test.txt"; // 表示する添付ファイル名 string filename = "test.txt"; // ルーム番号 string roomID = "000000000"; // トークン string apikey = "**************************************"; // 拡張子に対応したコンテンツタイプ string _type = Contents_type(filePath); // 文字コードを指定する var enc = Encoding.GetEncoding("UTF-8"); // UP先URL string url = string.Format("https://api.chatwork.com/v2/rooms/{0}/files", roomID); // 単に起動から現在までの時間を取得 string boundary = System.Environment.TickCount.ToString(); // インスタンス var req = WebRequest.Create(url); // メソッドをPOSTに設定 req.Method = "POST"; // コンテンツタイプをファイルに設定 req.ContentType = "multipart/form-data; boundary=" + boundary; //POST送信するデータを作成 string postData = ""; postData = "--------------------------" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"" + filename + "\"\r\n" + "Content-Type: " + _type + "\r\n\r\n"; // 送信するファイルを開く System.IO.FileStream fs = new System.IO.FileStream( filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read); // 読取準備 System.IO.BinaryReader br = new System.IO.BinaryReader(fs); // ファイルをバイナリで読み取る byte[] readData = br.ReadBytes((Int32)fs.Length); fs.Close(); var _postData = enc.GetBytes(postData).ToList(); _postData.AddRange(readData); // メッセージ追加 postData = "\r\n--------------------------" + boundary + "\r\n"; postData += "Content-Disposition: form-data; name=\"message\"\r\n\r\n"; postData += "I attached comment to chat.\r\n"; postData += "--------------------------" + boundary + "--"; _postData.AddRange(enc.GetBytes(postData)); // 送信バイナリデータの長さを指定 req.ContentLength = _postData.Count(); // トークン設定 req.Headers.Add(string.Format("X-ChatWorkToken: {0}", apikey)); // データをPOST送信するためのStreamを取得 System.IO.Stream reqStream = req.GetRequestStream(); // POSTで書込み //reqStream.Write(_postData, 0, _postData.Length); reqStream.Write(_postData.ToArray(), 0, _postData.Count); // 書込みストリームを閉じる reqStream.Close(); // サーバーからの応答を受信する System.Net.HttpWebResponse res = (System.Net.HttpWebResponse)req.GetResponse(); // 応答データを受信するためのStreamを取得 var resStream = res.GetResponseStream(); // 受信して表示 var sr = new StreamReader(resStream, enc); // 結果受信 var responseMessage = sr.ReadToEnd(); }
まずは元のファイルとどこがどういうふうに違うのかを調べてください。そして、その結果を提示しましょう
ありがとうございます。
元のエクセルファイルには、セルA1に「TEST」と入力したものがあり、
アップロード後のエクセルファイルを開きますと、
「ファイル形式またはファイル拡張子が正しくありません。」とエラーのポップが出て
エクセルが正しく開かないのです。
その元ファイルとアップロード後のやつをバイナリ比較して、どこがどういうふうに違うのかを調べてみよう
BitConverter.ToString すると 12-34-56 のような形式のテキストになりますが、これに対応してるんでしょうか?
Base64 とか octet-stream でなくていいんですか?
https://github.com/yoheiMune/frontend-playground/tree/master/024-multipart-form-data#post-body-1
調べてみると、バイナリをテキスト化せずそのまま入れるみたいですね。
y_waiwaiさん
いつもありがとうございます。アップロード前のファイルバイト数は8859で
アップロード後のファイルバイト数は17720で全く別物でしたー。
Zuishinさん ありがとうございます!
そのまま入れるとは。。。。? テキストファイルなんかだとわかるのですが、
イメージファイルも同じくでしょうか?
Stream なので BinaryWriter で書き込むのがいいと思います。
Zuishinさん ありがとうございます。
調べてみましたのですが自己解決できませんでした。
StringにBinaryWriter でバイナリを書き込むということでしょうか?
String ではなく Stream です。
> // データをPOST送信するためのStreamを取得
Zuishinさん ありがとうございます。
ファイルアップはされましたが結果は同じでした。
試しにファイルのバイナリデータの部分だけを
reqStream.Write(_postData, 0, _postData.Length); ↓
foreach(byte _b in readData) reqStream.WriteByte(_b);
とし、他をStream で書き込んでみましたら、ファイルがアップされず無反応でした。
(エラーは出ませんでした。)
その Stream をファイルの Stream に差し替えて、実際にフォーマットに従ったファイルになるかどうか確かめてみてください。
アップロードするかわりにファイルに書き込むということです。
Zuishinさん ありがとうございます。
試しに中身が「あいうえお」のテキストファイルをプログラムの記載内容でバイナリ取得して
それをFileStreamで別名ファイルに書込みましたら、正しく「あいうえお」テキストファイルが復元されました。
ヘッダが無かったのなら間違ってますね。
Zuishinさん ありがとうございます。
ヘッダというのは、------- で始まる部分のことでしょうか?
それも含めて全部です。サーバーに送るフォーマットになっているかどうか確かめてください。
Zuishinさん ありがとうございます。
なるほど!すみません、先ほどはファイルのバイナリ部分だけを書き込んでました。
全て含めたバイナリをテキストファイルに書き込みますと中身はこうなっておりました。
--------------------------678522765
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
82A082A282A482A682A8
--------------------------678522765--
それでアップロードするとどうなりますか?
チャットワーク上に中身が「82A082A282A482A682A8」
と記載された、テキストファイルがアップされるのです。
あと
> 82A082A282A482A682A8
これはテキストのように見えますが、バイナリになっていますか?
それなら成功です。
バイナリをテキスト化しているので、あとはそれをバイナリのまま書き込むだけです。
現在のコードを質問を編集して追記してください。
はい。更新できました。
Zuishinさんの話を再考して、再度コードを書き換えました。
結果テキストファイルは正しくアップロードされました!
次にエクセルファイルをアップロードしますと、前回までは拡張子が違うとアナウンスされましたが
今回は、「一部の内容に問題が見つかりました。可能な限り内容を回復しますか?」
と、おしいところまで進みました!
(回復しても開けませんでした。。。)
それをダウンロードしてオリジナルとどこが違うか比較してみてください。
Excel だと比較が難しいかもしれないので、半角文字のみの UTF8 テキストファイルで試すのが良いかもしれません。ファイルサイズや改行コードなども比べてください。
Zuishinさん ありがとうございます。
「abcde」と記載したテキストファイルをUTF-8で作成して比較してみました。
バイナリの比較ですが、
作成前 EF-BB-BF-61-62-63-64-65
作成後 EF-BB-BF-61-62-63-64-65-0D-0A
と、おっしゃる通り末尾に 0D-0A の改行コードが追加されていました。
一応確認しましたが、アップ時点ではファイルバイナリに改行コードは付いておりません。
これ、対策方法ってあるのでしょうか。。。?
バイナリのすぐ後に改行を挿入していたのを削除しました。
バイナリ直後のバウンダリの中の "\r\n" がそれです。
これを外してやってみてください。
Zuishinさん ありがとうございます! 正しくアップロードできました!
あと、下に書いてくれていたの先ほど気づきました。。。生意気に編集してしまったようなコードなので
ご指導いただいたコードに修正して、アップロードが完成したものに書き換えました。
根気強くお付き合いいただきまして誠にありがとうございます。感謝です!
あと、少し変更点ありました。
最後の頭の改行コードを抜くと、テキストファイルの中身がこうなってしまいまして、
abcde--------------------------690051812
Content-Disposition: form-data; name="message"
I attached comment to chat.
メッセージを追加して、そのバウンダリの頭に改行コードを入れると成功いたしました。
postData = "\r\n(←コレ)--------------------------" + boundary + "\r\n";
postData += "Content-Disposition: form-data; name=\"message\"\r\n\r\n";
ありがとうございました!
成功してなによりです。
回答1件
あなたの回答
tips
プレビュー