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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ChatWork

業務の効率化を目的としたコミュニケーションツール。 グループチャット、ビデオ・音声通話、ファイル共有、タスク管理などの機能を備えています。マルチデバイス対応で、ブラウザだけでなくタブレットやスマートフォンでも利用可能です。

Q&A

解決済

1回答

1096閲覧

C# で ChatWork にエクセルファイルをアップロードしたい

Com

総合スコア30

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ChatWork

業務の効率化を目的としたコミュニケーションツール。 グループチャット、ビデオ・音声通話、ファイル共有、タスク管理などの機能を備えています。マルチデバイス対応で、ブラウザだけでなくタブレットやスマートフォンでも利用可能です。

0グッド

0クリップ

投稿2019/03/11 10:27

編集2019/03/12 08:57

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(); }

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

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

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

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

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

y_waiwai

2019/03/11 10:34

まずは元のファイルとどこがどういうふうに違うのかを調べてください。そして、その結果を提示しましょう
Com

2019/03/11 10:39

ありがとうございます。 元のエクセルファイルには、セルA1に「TEST」と入力したものがあり、 アップロード後のエクセルファイルを開きますと、 「ファイル形式またはファイル拡張子が正しくありません。」とエラーのポップが出て エクセルが正しく開かないのです。
y_waiwai

2019/03/11 10:44

その元ファイルとアップロード後のやつをバイナリ比較して、どこがどういうふうに違うのかを調べてみよう
Zuishin

2019/03/11 10:53

BitConverter.ToString すると 12-34-56 のような形式のテキストになりますが、これに対応してるんでしょうか? Base64 とか octet-stream でなくていいんですか?
Com

2019/03/11 11:45

y_waiwaiさん いつもありがとうございます。アップロード前のファイルバイト数は8859で アップロード後のファイルバイト数は17720で全く別物でしたー。 Zuishinさん ありがとうございます! そのまま入れるとは。。。。? テキストファイルなんかだとわかるのですが、 イメージファイルも同じくでしょうか?
Zuishin

2019/03/11 12:12

Stream なので BinaryWriter で書き込むのがいいと思います。
Com

2019/03/12 03:36

Zuishinさん ありがとうございます。 調べてみましたのですが自己解決できませんでした。 StringにBinaryWriter でバイナリを書き込むということでしょうか?
Zuishin

2019/03/12 03:38

String ではなく Stream です。 > // データをPOST送信するためのStreamを取得
Com

2019/03/12 04:43

Zuishinさん ありがとうございます。 ファイルアップはされましたが結果は同じでした。 試しにファイルのバイナリデータの部分だけを reqStream.Write(_postData, 0, _postData.Length); ↓ foreach(byte _b in readData)  reqStream.WriteByte(_b); とし、他をStream で書き込んでみましたら、ファイルがアップされず無反応でした。 (エラーは出ませんでした。)
Zuishin

2019/03/12 04:47

その Stream をファイルの Stream に差し替えて、実際にフォーマットに従ったファイルになるかどうか確かめてみてください。 アップロードするかわりにファイルに書き込むということです。
Com

2019/03/12 05:11

Zuishinさん ありがとうございます。 試しに中身が「あいうえお」のテキストファイルをプログラムの記載内容でバイナリ取得して それをFileStreamで別名ファイルに書込みましたら、正しく「あいうえお」テキストファイルが復元されました。
Zuishin

2019/03/12 05:20

ヘッダが無かったのなら間違ってますね。
Com

2019/03/12 05:22

Zuishinさん ありがとうございます。 ヘッダというのは、------- で始まる部分のことでしょうか?
Zuishin

2019/03/12 05:27

それも含めて全部です。サーバーに送るフォーマットになっているかどうか確かめてください。
Com

2019/03/12 05:39

Zuishinさん ありがとうございます。 なるほど!すみません、先ほどはファイルのバイナリ部分だけを書き込んでました。 全て含めたバイナリをテキストファイルに書き込みますと中身はこうなっておりました。 --------------------------678522765 Content-Disposition: form-data; name="file"; filename="test.txt" Content-Type: text/plain 82A082A282A482A682A8 --------------------------678522765--
Zuishin

2019/03/12 05:48

それでアップロードするとどうなりますか?
Com

2019/03/12 05:49

チャットワーク上に中身が「82A082A282A482A682A8」 と記載された、テキストファイルがアップされるのです。
Zuishin

2019/03/12 05:50

あと > 82A082A282A482A682A8 これはテキストのように見えますが、バイナリになっていますか?
Zuishin

2019/03/12 05:51

それなら成功です。 バイナリをテキスト化しているので、あとはそれをバイナリのまま書き込むだけです。 現在のコードを質問を編集して追記してください。
Com

2019/03/12 07:05 編集

はい。更新できました。
Com

2019/03/12 07:41

Zuishinさんの話を再考して、再度コードを書き換えました。 結果テキストファイルは正しくアップロードされました! 次にエクセルファイルをアップロードしますと、前回までは拡張子が違うとアナウンスされましたが 今回は、「一部の内容に問題が見つかりました。可能な限り内容を回復しますか?」 と、おしいところまで進みました! (回復しても開けませんでした。。。)
Zuishin

2019/03/12 07:46

それをダウンロードしてオリジナルとどこが違うか比較してみてください。 Excel だと比較が難しいかもしれないので、半角文字のみの UTF8 テキストファイルで試すのが良いかもしれません。ファイルサイズや改行コードなども比べてください。
Com

2019/03/12 08:28

Zuishinさん ありがとうございます。 「abcde」と記載したテキストファイルをUTF-8で作成して比較してみました。 バイナリの比較ですが、 作成前 EF-BB-BF-61-62-63-64-65 作成後 EF-BB-BF-61-62-63-64-65-0D-0A と、おっしゃる通り末尾に 0D-0A の改行コードが追加されていました。 一応確認しましたが、アップ時点ではファイルバイナリに改行コードは付いておりません。 これ、対策方法ってあるのでしょうか。。。?
Zuishin

2019/03/12 08:31

バイナリのすぐ後に改行を挿入していたのを削除しました。 バイナリ直後のバウンダリの中の "\r\n" がそれです。 これを外してやってみてください。
Com

2019/03/12 09:00

Zuishinさん ありがとうございます! 正しくアップロードできました! あと、下に書いてくれていたの先ほど気づきました。。。生意気に編集してしまったようなコードなので ご指導いただいたコードに修正して、アップロードが完成したものに書き換えました。 根気強くお付き合いいただきまして誠にありがとうございます。感謝です!
Com

2019/03/12 09:03

あと、少し変更点ありました。 最後の頭の改行コードを抜くと、テキストファイルの中身がこうなってしまいまして、 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"; ありがとうございました!
Zuishin

2019/03/12 09:04

成功してなによりです。
guest

回答1

0

ベストアンサー

postdata は文字列です。
これを enc.GetBytes でバイナリに直して書き込んでいますが、その前に送信すべきデータまで文字列化して postdata の中に入れてしまっています。

以下の部分を変更してその次のコードのようにしてください。

C#

1// バイナリ文字列を追加 2postData += BitConverter.ToString(readData).Replace("-", string.Empty) + "\r\n"; 3 4// メッセージ追加 5//postData += "--------------------------" + boundary + "\r\n"; メッセージ部分はとりあえず退避 6//postData += "Content-Disposition: form-data; name=\"message\"\r\n\r\n"; 7//postData += "I attached comment to chat.\r\n"; 8postData += "--------------------------" + boundary + "--"; 9 10// 送信データをバイナリ化 11byte[] _postData = enc.GetBytes(postData);

C#

1var _postData = enc.GetBytes(postData).ToList(); 2_postData.AddRange(readData); 3 4// メッセージ追加 5postData = "--------------------------" + boundary + "\r\n"; 6postData += "Content-Disposition: form-data; name=\"message\"\r\n\r\n"; 7postData += "I attached comment to chat.\r\n"; 8postData += "--------------------------" + boundary + "--"; 9_postData.AddRange(enc.GetBytes(postData));

また、以下の部分をその次のコードに変えてください。

C#

1// POSTで書込み 2//reqStream.Write(_postData, 0, _postData.Length); 3foreach (byte _b in _postData) reqStream.WriteByte(_b);

C#

1// POSTで書込み 2//reqStream.Write(_postData, 0, _postData.Length); 3reqStream.Write(_postData.ToArray(), 0, _postData.Count);

投稿2019/03/12 06:32

編集2019/03/12 08:30
Zuishin

総合スコア28656

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問