Issues with writing BLOB data in chunk (8k) - asp.net

I'm trying to write BLOB data on to a word file. Here is my code
Dim reportID As Integer
reportID = table1.report_output_data_id
Dim aSqlStr As String = "SELECT file_data FROM table2 WHERE report_output_data_id = " + Convert.ToString(reportID )
Dim reader As SqlDataReader = CType(WebSession.DataObjectFactory.GetDataProvider("EGDatabase"), cDataProviderSQL).PopulateDataReader(aSqlStr)
' The size of the BLOB buffer.
Dim bufferSize As Integer = 8192
' The BLOB byte() buffer to be filled by GetBytes.
Dim outByte(bufferSize - 1) As Byte
' The bytes returned from GetBytes.
Dim retval As Long
' The starting position in the BLOB output.
Dim startIndex As Long = 0
Do While reader.Read()
' Reset the starting byte for a new BLOB.
startIndex = 0
' Read bytes into outByte() and retain the number of bytes returned.
retval = reader.GetBytes(0, startIndex, outByte, 0, bufferSize)
' Continue while there are bytes beyond the size of the buffer.
Do While retval = bufferSize
Response.BinaryWrite(outByte)
' Reposition start index to end of the last buffer and fill buffer.
startIndex += bufferSize
retval = reader.GetBytes(0, startIndex, outByte, 0, bufferSize)
Loop
Response.BinaryWrite(outByte)
Loop
reader.Close()
I'm writing 8k at a time as I had out of memory issues earlier when data is large say 1GB. Instead of the above code, If I use
Response.BinaryWrite(table2.file_data)
Everything works fine.
So please tell me whats the issue in using sqldatareader?
The file size currently I'm considering is 31794 bytes
FYI: I'm using CommandBehavior.SequentialAccess

Junk data was getting added on to the file while writing the BLOB data.
For example for a file size 33959 bytes
Loop 1 will process 0 - 8192 bytes ( increments of 8k)
Loop 2 8192 - 16384
Loop 3 16384 - 24576
Loop 4 24576 - 32768
Loop 5 32768 - 33959 ( actual file size)
retval = reader.GetBytes(0, startIndex, outByte, 0, bufferSize)
Here in the loop 5 we have only 1191 bytes. So in the outbyte array the first 1191 items will be replaced with the bytes read by reader at this point of time which is 1191 but the remaining items in the outbyte array will still hold junk values ( that is present from previous loops) as the outbyte array is 8k in size.
So used a new outbyte array instead of the default one(8k) if remaining data to be written is less than 8k. Here is the code changes.
Dim aSqlStr As String = "SELECT datalength(file_data),file_data FROM table2 WHERE report_output_data_id = " + Convert.ToString(reportID )
Dim reader As SqlDataReader = CType(WebSession.DataObjectFactory.GetDataProvider("EGDatabase"), cDataProviderSQL).PopulateDataReader(aSqlStr)
' The size of the BLOB buffer.
Dim bufferSize As Integer = 8192
' The BLOB byte() buffer to be filled by GetBytes.
Dim outByte(bufferSize - 1) As Byte
' The bytes returned from GetBytes.
Dim retval As Long
' The starting position in the BLOB output.
Dim startIndex As Long = 0
Do While reader.Read()
' Get file size from BLOB buffer.
fileSize = reader.GetInt32(0)
If fileSize > bufferSize Then
' Reset the starting byte for a new BLOB.
startIndex = 0
' Read bytes into outByte() and retain the number of bytes returned.
retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize)
' Continue while there are bytes beyond the size of the buffer.
Do While retval = bufferSize
Response.BinaryWrite(outByte)
' Reposition start index to end of the last buffer and fill buffer.
startIndex += bufferSize
Dim aRemainingBytes = fileSize - startIndex
If Not aRemainingBytes < bufferSize Then
retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize)
Else
Dim outByteRemaining(aRemainingBytes - 1) As Byte
retval = reader.GetBytes(1, startIndex, outByteRemaining, 0, aRemainingBytes)
Response.BinaryWrite(outByteRemaining)
End If
Loop
Else
Response.BinaryWrite(aReportOutput.GetRelatedPropertyValue("ReportOutputData.FileData"))
End If
Loop
reader.Close()

Related

Padding is invalid and cannot be removed. Padding Zeros works but ANSIX923, ISO10126 or PKCS7 do not

Edit: Here is a .NET fiddle of the issue
I am currently trying to write a process which encrypts files sent in as streams of Byte. The AES library does not seem to be applying padding correctly.
When I try to do an encryption I get cipher bytes like this:
... 50 57 243 226 18 0 0 0 0 0 0 0 0 0 ... (about 30,000 0s appended to the end)
When i think I should be getting cipher bytes like this (using PKCS7) :
... 50 57 243 226 18 9 9 9 9 9 9 9 9 9
How do I get the actual padding method to be recognised and return padding like the PKCS7?
Public Function Encrypt(InputStream As Stream) As Byte()
Dim outputStream = New MemoryStream()
Dim EncryptionKey As String = "MAKV2SPBNI99212"
Using encryptor As Aes = Aes.Create()
Dim pdb As New Rfc2898DeriveBytes(EncryptionKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
encryptor.Key = pdb.GetBytes(32)
encryptor.IV = pdb.GetBytes(16)
Using cs As New CryptoStream(outputStream, encryptor.CreateEncryptor(), CryptoStreamMode.Write)
Dim data As Integer
While (Assign(data, InputStream.ReadByte())) <> -1
cs.WriteByte(CByte(data))
End While
End Using
End Using
Return outputStream.GetBuffer()
End Function
Public Function Decrypt(InputStream As Stream) As Byte()
Dim outputStream = New MemoryStream()
Dim EncryptionKey As String = "MAKV2SPBNI99212"
Using encryptor As Aes = Aes.Create()
Dim pdb As New Rfc2898DeriveBytes(EncryptionKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
encryptor.Key = pdb.GetBytes(32)
encryptor.IV = pdb.GetBytes(16)
Using cs As New CryptoStream(InputStream, encryptor.CreateDecryptor(), CryptoStreamMode.Read)
Dim data As Integer
While (Assign(data, cs.ReadByte())) <> -1
outputStream.WriteByte(CByte(data))
End While
End Using
End Using
Return outputStream.GetBuffer
End Function
Private Function Assign(Of T)(ByRef source As T, ByVal value As T) As T
source = value
Return value
End Function
You shouldn't be using the .GetBuffer method on the returned MemoryStreams. .GetBuffer returns the underlying array which is typically larger than the amount of data in the Stream. That's why you are seeing the extra 0's at the end, and why the padding is failing to be read properly. See the remarks section in the documentation for the MemoryStream.GetBuffer Method
What you should be doing instead is calling outputStream.ToArray which will return a Byte array containing only the relevant data contained in the Stream, without all the trailing 0's.

Conversion of BitmapImage to Byte array and Store it Into Sql Database

I want to store bitmap image to byte, but in run time i'm getting error like
Conversion From type Image Format to Type Integer is Not Valid
Please Any one Help Me
For Each file As UploadedFile In` DOC.UploadedFiles`
Context.Cache.Remove(Session.SessionID + "UploadedFile")
Dim stream As Stream = file.InputStream
GenerateThumbnails(0.5, stream)
Dim DocumentImgName = file.FileName
Dim imgData As Byte() = New Byte(ViewState("CompressedImageData")) {}
Dim DocumentSplit = DocumentImgName.Split(".")
Dim ImgName = DocumentSplit(0)
Dim ImgExt = DocumentSplit(1)
stream.Read(imgData, 0, imgData.Length)
ViewState("imgData") = imgData
ViewState("FileName") = ImgName
ViewState("FileExtension") = ImgExt
Dim ms As New MemoryStream()
ms.Write(imgData, 0, imgData.Length)
Next
Private Sub GenerateThumbnails(ByVal scaleFactor As Double, ByVal sourcePath As Stream)
Using image__1 = Image.FromStream(sourcePath)
' can given width of image as we want
Dim newWidth = CInt(image__1.Width * scaleFactor)
' can given height of image as we want
Dim newHeight = CInt(image__1.Height * scaleFactor)
Dim thumbnailImg = New Bitmap(newWidth, newHeight)
Dim thumbGraph = Graphics.FromImage(thumbnailImg)
thumbGraph.CompositingQuality = CompositingQuality.HighQuality
thumbGraph.SmoothingMode = SmoothingMode.HighQuality
thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic
Dim imageRectangle = New Rectangle(0, 0, newWidth, newHeight)
thumbGraph.DrawImage(image__1, imageRectangle)
ViewState("CompressedImageData") = image__1.RawFormat
End Using
End Sub
You Can Store an Image data after Convert it to Byte datatype as below:
Dim ms As New Syste.IO.MemoryStream
Me.PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)
Dim byteImage() As Byte = ms.ToArray
Then You can Store The byteImage() to a field wich its type is Image Or Varbinary.

How to compare two string in asp.net vb

I am Developing a web apps in Asp.net using vb.net language and i comparing two string using
"=" and
"String.Equals()"
but i get always false result
Dim decod As Decoder = Encoding.UTF8.GetDecoder()
Dim totByt As Byte() = Convert.FromBase64String(Request("numType"))
Dim chrCount As Integer = decod.GetCharCount(totByt, 0, totByt.Length)
Dim deco_char(chrCount) As Char
decod.GetChars(totByt, 0, totByt.Length, deco_char, 0)
Dim str As New String(deco_char)
If str = "MO" Or str.Equals("Mo") Then
//Do somthing
End If
Please see my Watch window output
Please tell me why this give me false condition and how to solve it.
Check out the documentation for String.Equals() and look at the possible values for 3rd parameter comparisionType
String.Equals("MO", str, StringComparison.OrdinalIgnoreCase))
The str variable has a length of 3, instead of 2, causing it to be different than "MO".
Proof:
Dim decod As Decoder = Encoding.UTF8.GetDecoder()
Dim totByt As Byte() = Convert.FromBase64String("TU8=")
Dim chrCount As Integer = decod.GetCharCount(totByt, 0, totByt.Length)
Dim deco_char(chrCount) As Char
decod.GetChars(totByt, 0, totByt.Length, deco_char, 0)
Dim str As New String(deco_char)
Dim result1 = str.StartsWith("MO") ' is true
Dim result2 = str.Equals("MO") ' is false
Dim length = str.Length ' is 3
So obviously str is not the same as "MO".
Remember that if you declare an array like:
Dim deco_char(2) ' an array of 3 elements
...the indexes of the elements range from 0 through 2, so it contains 3 elements.
Solution: if you replace line 4 with:
Dim deco_char(chrCount-1) As Char
.. it will work, because now (in your specific case) your array is of size 2 instead of 3.
Try this :
str.Equals("MO", StringComparison.CurrentCultureIgnoreCase);

How to limit the number of rows to be read in a CSV file using CSVReader in ASP.NET

I am using a csvReader in order to retrieve data from a csv file. My csv file consists of 500elements and I only need the first 300. How do I limit my csvReader in order to return only 300 elements?
Dim PressureTable As DataTable = GetDataTabletFromCSVFile(BackUpDirDminus1)
Console.WriteLine("Rows count:" + PressureTable.Rows.Count.ToString)
Console.ReadLine()
Using CSVReader As New TextFieldParser(BackUpDirDminus1)
CSVReader.SetDelimiters(New String() {","})
CSVReader.HasFieldsEnclosedInQuotes = True
'read column names
Dim colFields As String() = CSVReader.ReadFields()
'For Each column As String In colFields
While Not CSVReader.EndOfData
Dim fieldData As String() = CSVReader.ReadFields()
'Making empty value as null
For i As Integer = 0 To fieldData.Length-1
If fieldData(i) = "" Then
fieldData(i) = Nothing
End If
Next
PressureTable.Rows.Add(fieldData)
End While
End Using
Please help. Thanks
I suppose there should be a method name "ReadNextRecord()", so your while loop should be like
While CSVReader.ReadNextRecord()
Declare a int k =0
and do k++
Once K++ reaches 300, then you can End While.

Resizing an image in VB.NET

I have the following code in my IHttpHandler:
Dim MemoryStream1 As New System.IO.MemoryStream
MemoryStream1.Write(SqlDataReader1("cover"), 0, SqlDataReader1("cover").Length - 1)
Dim Bitmap1 As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(MemoryStream1)
Dim Width1 As Integer = Bitmap1.Width
Dim Height1 As Integer = Bitmap1.Height
Dim Width2 As Integer = 90
Dim Height2 As Integer = Height1 * Width1 / Width1
Dim Bitmap2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(Width2, Height2)
Dim Graphics1 As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(Bitmap2)
Graphics1.DrawImage(Bitmap1, 0, 0, Width2, Height2)
Dim MemoryStream2 As New System.IO.MemoryStream
Bitmap2.Save(MemoryStream2, System.Drawing.Imaging.ImageFormat.Png)
context.Response.BinaryWrite(MemoryStream2.ToArray)
It works but I'm not sure that it is the right way to resize an image. How to simplify that code?
Thanks in advance!
Public Function ResizeImage(imgToResize As Image, size As Size) As Byte()
Dim sourceWidth As Integer = imgToResize.Width
Dim sourceHeight As Integer = imgToResize.Height
Dim nPercent As Single = 0
Dim nPercentW As Single = 0
Dim nPercentH As Single = 0
nPercentW = (CSng(size.Width) / CSng(sourceWidth))
nPercentH = (CSng(size.Height) / CSng(sourceHeight))
If nPercentH < nPercentW Then
nPercent = nPercentH
Else
nPercent = nPercentW
End If
Dim destWidth As Integer = CInt(Math.Truncate(sourceWidth * nPercent))
Dim destHeight As Integer = CInt(Math.Truncate(sourceHeight * nPercent))
Dim b As New Bitmap(destWidth, destHeight)
Dim g As Graphics = Graphics.FromImage(DirectCast(b, Image))
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight)
g.Dispose()
Return b.ToByteArray()
End Function
This function will resize an image to a specified size keeping its proporstion. It was in C# and I put it through an online converter so may not be 100% correct
ToByteArray() is an extension method I wrote to store the image in a DB i can give you that also if you like.
Basically the code is correct, but there are some problems with it:
You are skipping the last byte when you write into the first memory stream. The last property in the Write call should be the length, not the length minus one.
Your calculation of Height2 is incorrect. The expression Height1 * Width1 / Width1 will always evaluate to the value of Height1. You should use Height1 * Width2 / Width1 instead.
You are not disposing your memory streams, bitmaps or graphics objects. Use Using blocks to make sure that the objects are disposed.
You can simplify the code somewhat by creating the first memory stream from the byte array instead of writing the array to the stream:
Using MemoryStream1 As New System.IO.MemoryStream(SqlDataReader1("cover"))
Using Bitmap1 As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(MemoryStream1)
Dim Width1 As Integer = Bitmap1.Width
Dim Height1 As Integer = Bitmap1.Height
Dim Width2 As Integer = 90
Dim Height2 As Integer = Height1 * Width2 / Width1
Using Bitmap2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(Width2, Height2)
Using Graphics1 As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(Bitmap2)
Graphics1.DrawImage(Bitmap1, 0, 0, Width2, Height2)
End Using
Using MemoryStream2 As New System.IO.MemoryStream
Bitmap2.Save(MemoryStream2, System.Drawing.Imaging.ImageFormat.Png)
context.Response.BinaryWrite(MemoryStream2.ToArray)
End Using
End Using
End Using
End Using

Resources