- PR -

【ASP】バイナリデータのDB読み書き

1
投稿者投稿内容
homes
常連さん
会議室デビュー日: 2002/08/06
投稿数: 38
投稿日時: 2006-11-01 17:31
ある入力フォームでファイルを添付してDB(SQLServer)にバイナリデータ
を書き込むプログラムを作成しています。
添付ファイルをアップロード後、その後対象ファイルをダウンロードして
テストをしてみました。
Excel、Word、exe、zip、lzh 等の一般的なファイルは問題なく開いたのですが、
xdw という拡張子のファイル
(富士ゼロックス社製のドキュワークスと呼ばれるソフトのファイルです)
を開くとファイルが壊れてしまって開かなくなっていました。
ファイルのアップ前とダウン後のサイズを確認すると、

元ファイルのサイズ
サイズ:156 KB (159,999 バイト)
ディスク上のサイズ:160 KB (163,840 バイト)

アップロードしてダウンロードしたファイルサイズ
サイズ:156 KB (160,000 バイト)
ディスク上のサイズ:160 KB (163,840 バイト)

となっており、どうやら1バイトだけ増えています。
ただ、圧縮した状態でアップし、ダウンロードすると
解凍後問題なく開きました。
私はバイナリデータを扱った経験が無くいろいろなサンプルを参考にして
作ったのですが、どなたかご教授頂ければ幸いです。
以下がソースです。

ファイルアップロード
Protected Sub btnInsert_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnInsert.Click
Dim objDB As New SqlConnection("Data Source=XXX;User ID=XXX;Password=XXX;Initial Catalog=XXX")
Dim objCom As New SqlCommand("Insert Into TEMPTBL (ID,ファイルタイプ,ファイル名,添付FILE) " & _
"Values (@ID,@FileType,@FileName,@Tenpu)", objDB)
objCom.Parameters.Add("@FileName", Path.GetFileName(Me.upFile.PostedFile.FileName))
objCom.Parameters.Add("@FileType", Me.upFile.PostedFile.ContentType)

Dim aryData(Me.upFile.PostedFile.ContentLength) As Byte
Me.upFile.PostedFile.InputStream.Read(aryData, 0, Me.upFile.PostedFile.ContentLength)
objCom.Parameters.Add("Tenpu", aryData)
objDB.Open()
objCom.ExecuteNonQuery()
objDB.Close()
End Sub

ファイルダウンロード
Protected Sub btnDownload_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim intID As Integer = Me.GridViewMessage.SelectedValue
Dim objRs As SqlDataReader
Dim objDB As New SqlConnection("Data Source=XXX;User ID=XXX;Password=XXX;Initial Catalog=XXX")
Dim objCom As New SqlCommand("Select ファイル名,ファイルタイプ,添付FILE From TEMPTBL Where ID=" & intID, objDB)
objDB.Open()
objRs = objCom.ExecuteReader()
If objRs.Read Then
Response.HeaderEncoding = Text.Encoding.GetEncoding("shift-jis")
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Disposition", " attachment;filename=" & HttpUtility.UrlEncode(CType(objRs.Item(0), String)))
Response.Flush()
Response.BinaryWrite(CType(objRs.Item(2), Byte()))
End If
objDB.Close()
Response.End()
End Sub

homes
常連さん
会議室デビュー日: 2002/08/06
投稿数: 38
投稿日時: 2006-11-01 18:02
先程のファイル、アップ前とアップ後のファイルを
バイナリエディタで開いて確認してみました。
するとアップ後のファイルには1バイト分だとは思うのですが、
データの最後の0f欄に
00が入っていました。
元のファイルの同じ場所はブランクになっていました。

どなたかよろしくお願い致します。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-11-01 22:05
可能なら、適当な 159,999 バイトのファイルを作って、試してみてください。

コードは読んでいませんが、他のファイルが処理できているのなら、何らかの条件で SQL Server とのやりとりの間で、余分なデータが追加されている可能性があります。

また、アップロードしたファイルを、DB に格納せずに、そのままファイルに格納してみてください。または、アップロードされたファイル(サーバ上)のバイト数は、どうなっていますか。
_________________
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2006-11-01 23:40
NAL-6295です。
引用:

homesさんの書き込み (2006-11-01 17:31) より:

Dim aryData(Me.upFile.PostedFile.ContentLength) As Byte




たぶん原因はここだと思います。
C#なら、指定したサイズの配列になりますが、
VB.NETの場合は、指定したIndexまでの配列になります。
Indexは0オリジンなので、Me.upFile.PostedFile.ContentLength+1分の配列を作ってしまうわけです。
だから
コード:

Dim aryData(Me.upFile.PostedFile.ContentLength - 1) As Byte



としたらうまく行くのではないでしょうか。

#VB.NETとC#を行き来しているとたまにやらかします。

[ メッセージ編集済み 編集者: NAL-6295 編集日時 2006-11-01 23:41 ]
homes
常連さん
会議室デビュー日: 2002/08/06
投稿数: 38
投稿日時: 2006-11-02 13:40
JittaさんNAL-6295さん、返信ありがとうございます。

なんとかNAL-6295さんの方法で解決できました。

私はこの
Me.upFile.PostedFile.ContentLength
を使うのは今回初めてでして、ContentLengthという最後の標記を
見て、長さを取得しているんだなと勝手な解釈をしていました。
しかも長さなのに0オリジンとは、某携帯キャリアではありませんが、
「予想外です」
対象のファイルをアップロード後にダウンロードしてデータ容量も
あっており、バイナリエディタで確認しても最後に00は付いていませんでした。

しかしExcelやその他のファイルでも同じ状態になっていたはずなのにExcel等では
開く事が出来たのが今となっては不思議でしょうがありません。
無事に解決できて良かったです。
本当にありがとうございました。
まるく
大ベテラン
会議室デビュー日: 2004/01/09
投稿数: 181
投稿日時: 2006-11-02 14:05
いやそうではなくて、配列の定義に指定する値の扱いが違うという話なのですよ。
って読んでくれるのか判らないけど。。。

[VB.NET]
Dim c(5) As Integer '要素0から要素5までの6個の器をつくる

[C#]
int[] c = new int[5]; //要素0から要素4までの5個の器をつくる
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2006-11-02 14:06
引用:

homesさんの書き込み (2006-11-02 13:40) より:
JittaさんNAL-6295さん、返信ありがとうございます。

なんとかNAL-6295さんの方法で解決できました。

私はこの
Me.upFile.PostedFile.ContentLength
を使うのは今回初めてでして、ContentLengthという最後の標記を
見て、長さを取得しているんだなと勝手な解釈をしていました。
しかも長さなのに0オリジンとは、某携帯キャリアではありませんが、
「予想外です」




ContentLengthに入っているのは長さですよ。
配列の宣言に問題があったのです。
予想外ではなく、仕様通りにやればちゃんとできます。
0オリジンが予想外という事は、今まで配列は1から参照していたのですか?

私が前述した
引用:

C#なら、指定したサイズの配列になりますが、
VB.NETの場合は、指定したIndexまでの配列になります。



というのは、配列の宣言の話です。
ContentLengthは何も関係ありません。

一度、対象言語の仕様を理解されてはいかがでしょうか?
homes
常連さん
会議室デビュー日: 2002/08/06
投稿数: 38
投稿日時: 2006-11-02 14:59
みなさま、大変申し訳ありません。
書いた後に気づきました・・・。

配列の話の事ですよね
aryData(ここですよね)

送信後、自分の勘違いに気づき、
顔が真っ赤になりました。
失礼致しました。
1

スキルアップ/キャリアアップ(JOB@IT)