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

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

新規登録して質問してみよう
ただいま回答率
85.48%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

C#

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

Q&A

3回答

6003閲覧

C# http通信で受信したファイルが壊れてしまっている

The8

総合スコア11

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

C#

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

0グッド

1クリップ

投稿2019/08/04 10:03

編集2019/08/04 10:51

前提・実現したいこと

C#でhttp通信をするサーバーとクライアントを作成しています。
http通信でクライアントから動画をサーバーに送りたいです。

発生している問題・エラーメッセージ

サーバーで、クライアントから受信したbyte配列をmp4ファイルに変換してもmp4ファイルが壊れてしまっている

該当のソースコード

C#

1var context = listener.GetContext(); 2context.Response.ContentType = "video/mp4"; 3var video = new StreamReader(context.Request.InputStream).ReadToEnd(); //postされたデータをstringに 4byte[] videobytes = Encoding.GetEncoding("shift_jis").GetBytes(video); 5FileStream vidFile = new FileStream(@"C:\Users\ig_ei\OneDrive\Desktop\test.mp4", FileMode.Create); 6BinaryWriter writer = new BinaryWriter(vidFile); 7writer.Write(video); //バイト配列をファイルに書き出し

↑サーバーサイドのコードです。

試したこと

元の動画と壊れてしまっている動画の拡張子をtxtに変えて中身を見たところ構成がとても似ていたので文字化けしてしまっているだけだと思います。サーバーサイドで文字コードを指定する必要があるのでしょうか?

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2019/08/04 10:12

意味不明です。単にクライアントの PC からファイルをサーバーにアップロードできれば良いのですか? サーバー側、クライアント側のアプリは何なのですか? 「該当のソースコード」というのは一体何をするものなのですか?
The8

2019/08/04 10:38

すみません、情報不足でした クライアントのpcからサーバーにファイルをアップロードしたいです その際http通信で転送しようと思うのですが、どうも送られてきたファイルが壊れてしまっているようです。 ソースコードはサーバーサイドのもので、クライアントからpostで送られたデータをbyte配列に変換して最終的にファイルに書き出してます。
takasima20

2019/08/04 11:19

C# は知らんけど "shift_jis" とか関係あるのかな?
退会済みユーザー

退会済みユーザー

2019/08/04 11:22

サーバー側、クライアント側のアプリは何なのですか?
退会済みユーザー

退会済みユーザー

2019/08/04 11:53

上の意味が分かりますか? 例えば、「サーバー側が ASP.NET Web Forms アプリ、クライアント側が Windows Forms アプリ」といった答えを書いてほしいと言っているのですよ。
The8

2019/08/04 12:37

クライアント、サーバーどちらも.Net frameworkのコンソールアプリケーションです
退会済みユーザー

退会済みユーザー

2019/08/04 14:07 編集

> クライアント、サーバーどちらも.Net frameworkのコンソールアプリケーションです クライアントはコンソールアプリでよくても、サーバー側はコンソールアプリでは全くダメ&問題外です。このまま話を続けても、質問者さんの知識不足で話が通じないと思います。もっと勉強してきてください。
YAmaGNZ

2019/08/04 22:45

HttpListenerクラスを使えば、簡易なHTTPサーバをコンソールアプリで作成できるかと 出来ることは限られるかもしれませんが、問題外ではないでしょう。
退会済みユーザー

退会済みユーザー

2019/08/04 23:37

自力で http サーバーを実装しているということですか? そうだとしたら「全くダメ&問題外」ということはなかったですね。 失礼しました > 質問者さん
guest

回答3

0

postされたデータをそのままファイルに書けばいいのではないでしょうか?

C#

1using (FileStream fs = new FileStream(@"C:\Users\ig_ei\OneDrive\Desktop\test.mp4", FileMode.Create)) 2{ 3 context.Request.InputStream.CopyTo(fs); 4} 5

また、レスポンスの返しがおかしいかと思います。
レスポンスでmp4を返すわけではないと思いますので、
context.Response.ContentType = "video/mp4";
とするのではなく

C#

1context.Response.StatusCode = 200; 2context.Response.ContentType = "text/html"; 3using (StreamWriter writer = new StreamWriter(context.Response.OutputStream, Encoding.UTF8)) 4 writer.WriteLine("Ok"); 5 6context.Response.Close();

と正常に受信した旨を返すべきかと思います。

投稿2019/08/05 01:42

YAmaGNZ

総合スコア10242

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

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

0

「テキストファイル」「バイナリファイル」と分けることもありますが、ファイルは全て「バイナリ」です。
決まった範囲の値しかない場合、あるいは、ある決まりの下に解釈すると印字可能な文字に置き換えられるコードだけで構成されているバイナリファイルを、特に「テキストファイル」と呼びます。
この、「ある決まり」が、Shift JIS であったり、EUC であったり、UTF-8 などです。
さて、mp4 ファイルということですが、これはバイナリファイルです。どう解釈しても、印字可能な文字だけで構成されているわけではありません。ですから、「文字化けする」なんてあり得ないし、逆に、Encoding.GetEncoding("shift_jis").GetBytes(video)などとして「データ化け」させています。

投稿2019/08/04 14:30

Q71

総合スコア995

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

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

0

送信側がどうなっているか書いてないので分かりませんが、ファイルアップロードでバイナリデータをサーバーに送信する場合、普通 "multipart/form-data" 形式にするはずです。

質問者さんの送信用コンソールアプリも多分そうしていると想像しています。

さらに、受信側は HttpListener を利用したアプリで、質問のコードにある変数 listener が HttpListner オブジェクトを指していると理解しています。

その想像が当たっているとすると、そう簡単にはいかないはずです。

なぜなら、"multipart/form-data" 形式でファイルを送信するとその内容は以下のようになりますが(Fiddler でのキャプチャ画像)、この中で目的のファイルのバイト配列は赤枠で囲った部分になります(実際はこの下にずっと続きます)。

イメージ説明

この赤枠部分をバイト配列として切り出してきてファイルとして保存するという操作が必要です。

そうするためには、要求ヘッダから boundary を探してきてそれを基準に各部分に分けて、分けた中からファイルの部分を探して上の赤枠部分のバイト配列を取得することになるはずです。

ググって調べてみるとそういうことを考えた人はいるようです。

Httplistener and file upload
https://stackoverflow.com/questions/8466703/httplistener-and-file-upload

回答も付いていますので見てください。検証はしてませんが、かなり大変なのは分かるかと思います。

という訳で、コンソールアプリでは「全くダメ&問題外」ということはないにしても、かなりの無理筋のような気がします。

サーバー側を ASP.NET にすれば、そのあたりはフレームワークが面倒を見てくれて、ごく簡単にアップロードされたファイルを保存できますので、コンソールアプリで実装するというのが必須でなければ、そちらの方向に進むのがお勧めです。

投稿2019/08/05 03:16

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

YAmaGNZ

2019/08/05 03:29

"multipart/form-data"ではなく"application/octet-stream"でPOSTすればHttplistenerのRequest.InputStreamをそのまま保存で送信元のバイナリと差異がないことを確認してますので、無理筋でもないと思います。
退会済みユーザー

退会済みユーザー

2019/08/05 03:48

HttpListener で無理筋でないように送信側を実装すれば無理筋ではなくなるのは当たり前ですよね。 何が普通かについてはいろいろ議論があるかもしれませんが、自分的には "multipart/form-data" 形式が普通と思っているので、その前提で無理筋です。
tamoto

2019/08/05 03:54

Web サイトからのアップロードでしたら form の multipart が一般的ですが、Http を直接使ってコンソールアプリのクライアントから投げているのなら body にバイナリを突っ込む形は極めて自然だと思います。そして、質問者さんの環境は後者だと読み取れます。
YAmaGNZ

2019/08/05 04:04

一般的なブラウザからのアップロードであれば仰るとおりだと思います。 ただ、質問にはクライアントも作成されているとのことでしたので、こうすれば出来るということを書かせてもらいました。
退会済みユーザー

退会済みユーザー

2019/08/05 04:15

web サーバー側も考えた場合は「body にバイナリを突っ込む形は極めて自然」はどうかは疑問です。 でも、そもそもがどういう形式で送受信するかという前提・条件が明確になってないところで議論が始まっているということがアレでしたね。その点、自分も反省。後は質問者さんのレスを待ちたいと思います。
KOZ6.0

2019/08/05 06:21

multipart/form-data は HTML の規格なので http とは切り離して考えるべきです。 元質問者が作っているのは http サーバーであって、web サーバーではないことに注意しましょう。
退会済みユーザー

退会済みユーザー

2019/08/05 06:57

個人的意見ですが、切っても切れないと思っています。HttpListener で無理筋でないように送信側を実装するというように閉じた世界で考えるのであればともかく、自分はそのようには考えてませんでした。質問者さんがそう考えているというのかどうかは質問からは不明ですし。
KOZ6.0

2019/08/05 07:57

html から見ると、たしかに http は切り離せない存在でしょう。 でも、http から html を見ると、そうでもないです。 普通に json を送ったり送られたりしてますし、WebDAV みたいなしくみもある。 まあ、これも私見といえば私見なんでしょうね。 質問の冒頭で 「C#でhttp通信をするサーバーとクライアントを作成しています。」 と書かれているのに Web サーバーという発想が出てくるのか私にはわからないです。 コードと「試したこと」から、おしいところまでいってるっていう様子がうかがえます。 うまくいかなかったらすぐ再質問がくるでしょうから、他の方の回答で解決しちゃってると思ってよいと思うんですけどね。 バイナリ読み出しのところで詰まってなきゃいいかな、という心配はあります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問