Cant open a closed file - asp.net

I am using the code below to try and open a pdf file and I am getting the error cannot open a closed file? Not sure what I am missing here.
Dim FileName As String
Dim FolderLocation As String = Nothing
Dim FileFormat As String = "application/pdf"
Dim tFileNameArray As Array = Nothing
Dim tFileName As String = Nothing
FileName = "\\Server\Files\45144584.pdf"
Dim fs As New FileStream(FileName, FileMode.Open, FileAccess.Read)
Using (fs)
End Using
Dim data() As Byte = New Byte(fs.Length) {}
Dim br As BinaryReader = New BinaryReader(fs)
br.Read(data, 0, data.Length)
br.Close()
Response.Clear()
Response.ContentType = FileFormat
Response.AppendHeader("Content-Disposition", "attachment; filename=" & tFileName.Split("\")(tFileName.Split("\").Length - 1))
Response.BufferOutput = True
Response.BinaryWrite(data)
Response.End()

You need to have all code that references fs inside of the using, otherwise you are attempting to access an object that has already been disposed. I would also do the same thing with the BinaryReader, since it also implements IDisposable:
Dim data() As Byte
Using fs As New FileStream(FileName, FileMode.Open, FileAccess.Read)
data = New Byte(fs.Length) {}
Using br As New BinaryReader(fs)
br.Read(data, 0, data.Length)
End Using
End Using
...

You have the following lines:
Using (fs)
End Using
After End Using, the file is closed and the fs object disposed of.
You need to put the code that reads from fs inside the using block.

Dim fs As New FileStream(FileName, FileMode.Open, FileAccess.Read)
Using (fs)
End Using
Dim data() As Byte = New Byte(fs.Length) {}
...
You're trying to use fs after it has been disposed. This needs to be:
Dim fs As New FileStream(FileName, FileMode.Open, FileAccess.Read)
Using (fs)
Dim data() As Byte = New Byte(fs.Length) {}
Dim br As BinaryReader = New BinaryReader(fs)
br.Read(data, 0, data.Length)
br.Close()
End Using

Related

Decrypting TS Files Individually

Could someone help me fix this code?
This is actually fully working but, this code will automatically merged the output files
I want to decrypt each file only and not automatically merged
Here's the code:
Sub decrypt()
Try
Cursor = Cursors.WaitCursor
Application.DoEvents()
If txtFileName.Text = "" Then
txtFileName.Text = "DecryptedFile"
Else
End If
Dim folder As String = txtSource.Text
Dim encryptionKey As Byte() = File.ReadAllBytes(txtKey.Text)
Dim outputFile As String = (txtFilePath.Text + "\" + txtFileName.Text + ".ts")
Using outputFileStream As FileStream = New FileStream(outputFile, FileMode.Create)
Dim files = Directory.GetFiles(folder, "*.ts")
For i As Integer = 0 To files.Length - 1
Dim encryptionIV As Byte() = New Byte(15) {}
Using inputFileStream As FileStream = New FileStream(files(i), FileMode.Open)
Using aes = New AesManaged With {
.Key = encryptionKey,
.IV = encryptionIV,
.Mode = CipherMode.CBC
}
Using encryptor = aes.CreateDecryptor()
Using cryptoStream = New CryptoStream(inputFileStream, encryptor, CryptoStreamMode.Read)
cryptoStream.CopyTo(outputFileStream)
End Using
End Using
End Using
End Using
Next
End Using
Cursor = Cursors.Default
Catch ex As Exception
Cursor = Cursors.Default
End Try
End Sub

Convert cURL to ASP.Net

I'm looking for a way to convert the following cURL to ASP.Net.
curl -F f=#example.pdf "https://pdftables.com/api?key=ZZZ999&format=xml"
I've used the following function extensively to get virtually any URL/content, but I'm lost on how to include a file located on the hosted web server.
Public Shared Function GetRemoteURL(getURL As String) As String
Dim objReq As HttpWebRequest
Dim objRsp As HttpWebResponse = Nothing
Dim objRdr As StreamReader
Dim objRes As String = ""
Try
objReq = DirectCast(WebRequest.Create(getURL), HttpWebRequest)
objRsp = DirectCast(objReq.GetResponse(), HttpWebResponse)
objRdr = New StreamReader(objRsp.GetResponseStream())
objRes = objRdr.ReadToEnd()
Catch
objRes = ""
Finally
If Not objRsp Is Nothing Then objRsp.Close()
End Try
Return objRes.ToString()
End Function
Any advice/direction would be deeply appreciated.
John
You'll have to set the request body, something like:
Public Function GetRemoteURL(getURL As String) As String
Dim objReq As HttpWebRequest
Dim objRsp As HttpWebResponse = Nothing
Dim objRdr As StreamReader
Dim objRes As String = ""
Try
objReq = DirectCast(WebRequest.Create(getURL), HttpWebRequest)
objReq.Method = "POST"
Dim postData = "f=#example.pdf"
Dim encoding As New ASCIIEncoding()
Dim bytes = encoding.GetBytes(postData)
objReq.ContentLength = bytes.Length
Dim stream = objReq.GetRequestStream()
stream.Write(bytes, 0, bytes.Length)
objRsp = DirectCast(objReq.GetResponse(), HttpWebResponse)
objRdr = New StreamReader(objRsp.GetResponseStream())
objRes = objRdr.ReadToEnd()
Catch
objRes = ""
Finally
If Not objRsp Is Nothing Then objRsp.Close()
End Try
Return objRes.ToString()
End Function
note: i didn't test this so it might not directly work.

Upload a document after saving it with agility pack fails

I've been struggling with some issue with an upload (thru FtpWebRequest) of a document after it's been saved with Html Agility pack.
I'm trying to edit a html file and then save it to a stringWriter and then upload it to a server.
I'm saving the document like this
...
doc.OptionAutoCloseOnEnd = True
doc.OptionWriteEmptyNodes = True
Dim sr As New StringWriter
doc.Save(sr)
And then upload it using asyncFtpUpload sub like the one on msdn but only with a few changes (instead of a filename I use the string)
http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx#Y3024
The result of this is that the file beeing uploaded get's the last bytes cut off.
When I see the source code of that file on the server, it misses the <\html> tag.
i have debugged the code and the string created on the doc.save() is correct, then in the upload routine, when i use the getBytes() it's still correct, and the requestStream write method writes the correct length of the stream.
I can't figure out what's happening with this code.
Can anyone help me figuring this out?
Here's the code:
Dim outStream As MemoryStream = New MemoryStream(ASCIIEncoding.Default.GetBytes(str))
Dim uploader As AsynchronousFtpUpLoader = New AsynchronousFtpUpLoader
uploader.startUpload(pag, outStream)
And the class:
Public Class AsynchronousFtpUpLoader
Public Sub startUpload(ByVal pag As FtpPage, ByVal stream As Stream)
Try
Dim waitObject As ManualResetEvent
Dim target As New Uri(pag.currentUrl)
Dim state As New FtpState()
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(target), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.UploadFile
request.UseBinary = False
request.Credentials = New NetworkCredential(pag.login, pag.password)
state.Request = request
state.stream = stream
' Get the event to wait on.
waitObject = state.OperationComplete
' Asynchronously get the stream for the file contents.
request.BeginGetRequestStream(New AsyncCallback(AddressOf EndGetStreamCallback), state)
' Block the current thread until all operations are complete.
waitObject.WaitOne()
' The operations either completed or threw an exception.
If state.OperationException IsNot Nothing Then
Throw state.OperationException
Else
End If
Catch ex As Exception
End Try
End Sub
Private Shared Sub EndGetStreamCallback(ByVal ar As IAsyncResult)
Dim state As FtpState = DirectCast(ar.AsyncState, FtpState)
Dim requestStream As Stream = Nothing
Try
requestStream = state.Request.EndGetRequestStream(ar)
Const bufferLength As Integer = 2048
Dim buffer As Byte() = New Byte(bufferLength) {}
Dim readBytes As Integer = 0
Dim stream As MemoryStream = state.stream
Do
readBytes = stream.Read(buffer, 0, bufferLength)
If readBytes <> 0 Then
requestStream.Write(buffer, 0, readBytes)
End If
Loop While readBytes <> 0
requestStream.Flush()
state.stream.Close()
requestStream.Close()
state.Request.BeginGetResponse(New AsyncCallback(AddressOf EndGetResponseCallback), state)
Catch e As Exception
state.OperationException = e
state.OperationComplete.[Set]()
Return
End Try
End Sub
Private Shared Sub EndGetResponseCallback(ByVal ar As IAsyncResult)
Dim state As FtpState = DirectCast(ar.AsyncState, FtpState)
Dim response As FtpWebResponse = Nothing
Try
response = DirectCast(state.Request.EndGetResponse(ar), FtpWebResponse)
response.Close()
state.StatusDescription = response.StatusDescription
state.OperationComplete.[Set]()
Catch e As Exception
state.OperationException = e
state.OperationComplete.[Set]()
End Try
End Sub

Combine multiple byte array images into one

I can create an image on the server from a byte array stored in the database. But how do I combine each byte array into one image. Basically I want to stack them on top of each other (they are all 1366px width and 618px height) and then save that to a png image. I will then get that image from the server and return to the web page (which I can do now for one image). Hope you can help.
This code in asp.net web forms creates an image which i return the filename as a return in a webmethod function back to the browser.
Public Shared Function Base64ToImage(ByVal base64String As String, ByVal id As String) As String
'http://www.dailycoding.com/Posts/convert_image_to_base64_string_and_base64_string_to_image.aspx
' Convert Base64 String to byte[]
Dim sFileName As String = String.Empty
Try
Dim imageBytes As Byte() = Convert.FromBase64String(base64String)
Dim ms As New MemoryStream(imageBytes, 0, imageBytes.Length)
' Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length)
Dim image__1 As Image = Image.FromStream(ms, True)
sFileName = "img_" & id & ".png"
Dim sPath As String = HttpContext.Current.Server.MapPath("images\")
image__1.Save(sPath & sFileName, System.Drawing.Imaging.ImageFormat.Png)
Catch ex As Exception
End Try
'
Return sFileName
End Function
I have tried this, looping through the records and then trying to combine them with sourcecopy but I can't get it to combine them?
Public Shared Function Base64ToImage2(ByVal dt As DataTable) As String
' Convert Base64 String to byte[]
Dim sFileName As String = String.Empty
Dim base64String As String, id As String
'if first record create image
'on 2nd or greater in dt then combine images
Try
Dim iCount As Integer = 0
Dim image__1 As Image = Nothing
Dim compositeImage As Image = Nothing
Dim sPath As String = String.Empty
If dt.Rows.Count > 0 Then
For Each myRow As DataRow In dt.Rows
'getImage = getImage() & Base64ToImage(myRow("image_data").ToString(), myRow("id").ToString()) & "|"
If iCount = 0 Then
Dim imageBytes As Byte() = Convert.FromBase64String(myRow("image_data").ToString())
Dim ms As New MemoryStream(imageBytes, 0, imageBytes.Length)
' Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length)
image__1 = System.Drawing.Image.FromStream(ms)
'sFileName = "img_1.png"
'sPath = HttpContext.Current.Server.MapPath("images\")
'image__1.Save(sPath & sFileName, System.Drawing.Imaging.ImageFormat.Png)
'compositeImage = New Bitmap(image__1.Width, image__1.Height)
Else
Dim imageBytes As Byte() = Convert.FromBase64String(myRow("image_data").ToString())
Dim ms2 As New MemoryStream(imageBytes, 0, imageBytes.Length)
' Convert byte[] to Image
ms2.Write(imageBytes, 0, imageBytes.Length)
Dim image__2 As Image = System.Drawing.Image.FromStream(ms2)
Dim g As Graphics = Graphics.FromImage(image__1)
g.CompositingMode = CompositingMode.SourceCopy
g.DrawImage(image__2, 0, image__1.Height)
sFileName = "img_1.png"
'sPath = HttpContext.Current.Server.MapPath("images\")
'image__2.Save(sPath & sFileName, System.Drawing.Imaging.ImageFormat.Png)
End If
iCount = iCount + 1
Next myRow
End If
'sFileName = "img_1.png"
'Dim sPath As String = HttpContext.Current.Server.MapPath("images\")
'compositeImage.Save(sPath & sFileName, System.Drawing.Imaging.ImageFormat.Png)
Catch ex As Exception
End Try
'
Return sFileName
End Function
Solved! After a ton of searching and reading I was able to combine png images into one! Each image is created from a memory stream and then appended to a bitmap with NewRectangle which is the key. Once I loop through the records from the database, I have one image which is downloaded to the client in a webmethod return. The width and height are pulled from the client to the webmethod and passed into the function so the image is scaled to fit the browser inner dimensions (to avoid any scrollbars).
JS on the client for the dimensions:
mywidth = window.innerWidth
myheight = window.innerHeight
The code to convert the base64 byte image is as follows...
Public Shared Function Base64ToImage2(ByVal dt As DataTable, ByVal Image_Width As String, ByVal Image_Height As String) As String
Dim sFileName As String = String.Empty
Dim sPath As String = HttpContext.Current.Server.MapPath("images\")
Dim myimage As Image = Nothing
' Create a new bitmap object 400 pixels wide by 60 pixels high
Dim objBitmap As New Bitmap(CInt(Image_Width), CInt(Image_Height))
'' Create a graphics object from the bitmap
Dim objGraphic As Graphics = Graphics.FromImage(objBitmap)
'if first record create image
'on 2nd or greater in dt then combine images
Try
If dt.Rows.Count > 0 Then
For Each myRow As DataRow In dt.Rows
Dim imageBytes As Byte() = Convert.FromBase64String(myRow("image_data").ToString())
Dim ms As New MemoryStream(imageBytes, 0, imageBytes.Length)
' Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length)
myimage = System.Drawing.Image.FromStream(ms)
objGraphic.DrawImage(myimage, New Rectangle(0, 0, CInt(Image_Width), CInt(Image_Height)))
Next myRow
sFileName = "img_1.png"
objBitmap.Save(sPath & sFileName, System.Drawing.Imaging.ImageFormat.Png)
End If
Catch ex As Exception
End Try
'
Return sFileName
End Function
In case someone else is looking for something similar in C# where you're trying to load an image source with the result, here's the code:
private void LoadImage()
{
string src = string.empty;
byte[] mergedImageData = new byte[0];
mergedImageData = MergeTwoImageByteArrays(watermarkByteArray, backgroundImageByteArray);
src = "data:image/png;base64," + Convert.ToBase64String(mergedImageData);
MyImage.ImageUrl = src;
}
private byte[] MergeTwoImageByteArrays(byte[] imageBytes, byte[] imageBaseBytes)
{
byte[] mergedImageData = new byte[0];
using (var msBase = new MemoryStream(imageBaseBytes))
{
System.Drawing.Image imgBase = System.Drawing.Image.FromStream(msBase);
Graphics gBase = Graphics.FromImage(imgBase);
using (var msInfo = new MemoryStream(imageBytes))
{
System.Drawing.Image imgInfo = System.Drawing.Image.FromStream(msInfo);
Graphics gInfo = Graphics.FromImage(imgInfo);
gBase.DrawImage(imgInfo, new Point(0, 0));
//imgBase.Save(Server.MapPath("_____testImg.png"), ImageFormat.Png);
MemoryStream mergedImageStream = new MemoryStream();
imgBase.Save(mergedImageStream, ImageFormat.Png);
mergedImageData = mergedImageStream.ToArray();
mergedImageStream.Close();
}
}
return mergedImageData;
}

Not able to open .pdf file in IE8

I've posted this question in asp.net web forum but no one replied.
I can't open "ONE" page of .pdf file using IE8 and give me an error message "the file is damaged and could not be repaired" when retrieved from SQL Server 2008, but more than one page I can open with no problem.
With Chrome I can open any number of .pdf pages.
The same page that I can't open using IE8 from DB, can be opened directly from hard disk using IE8.
My code in .asxh file:
context.Response.ContentType = "application/pdf"
Dim strm As Stream = ShowNewsImage(imgName)
If Not strm Is Nothing Then
Dim buffer As Byte() = New Byte(4095) {}
Dim byteSeq As Integer = strm.Read(Buffer, 0, 4096)
Do While byteSeq > 0
context.Response.OutputStream.Write(buffer, 0, byteSeq)
byteSeq = strm.Read(Buffer, 0, 4096)
Loop
context.Response.BinaryWrite(buffer)
End If
Thanks,
Ahmed.
Set Response.buffer to true and response.flush after finishing the PDF.
Seems too obvious but I have to ask... did you try this?
Response.WriteFile(imgName)
Link to documentation in case you're not familiar with this. :)
Proble solved.
I changed the buffer from Object to Byte and it worked !!!
The old code (part of a handler) :
context.Response.ContentType = "application/pdf"
Dim strm As Stream = ShowNewsImage(imgName)
If Not strm Is Nothing Then
Dim buffer As Byte() = New Byte(4095) {}
Dim byteSeq As Integer = strm.Read(buffer, 0, 4096)
Do While byteSeq > 0
context.Response.OutputStream.Write(buffer, 0, byteSeq)
byteSeq = strm.Read(buffer, 0, 4096)
Loop
context.Response.BinaryWrite(buffer)
context.Response.End()
End If
End Sub
Public Function ShowNewsImage(ByVal imgName As String) As Stream
Dim conn As String = ConfigurationManager.ConnectionStrings("Connection").ConnectionString
Dim connection As SqlConnection = New SqlConnection(conn)
Dim sql As String = "SELECT image FROM Table WHERE ID = #ID"
Dim cmd As SqlCommand = New SqlCommand(sql, connection)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("#ID", imgName)
connection.Open()
Dim img As <strong>Object </strong>= cmd.ExecuteScalar()
Try
Return New MemoryStream(CType(img, Byte()))
Catch
Return Nothing
Finally
connection.Close()
End Try
End Function
As you see, ExecuteScalar() attached the output to an Object.
I changed this to Byte:
context.Response.ContentType = "application/pdf"
Dim buffer As Byte() = New Byte(4095) {}
Dim byteSeq As Integer = 0
Dim conn As String = ConfigurationManager.ConnectionStrings("Connection").ConnectionString
Dim connection As SqlConnection = New SqlConnection(conn)
Dim sql As String = "SELECT image FROM Table WHERE ID = #ID"
Dim cmd As SqlCommand = New SqlCommand(sql, connection)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("#ID", imgName)
connection.Open()
buffer = cmd.ExecuteScalar()
context.Response.BinaryWrite(buffer)
context.Response.End()
No need to context.Response.OutputStream.Write , it is already impeded in context.Response.BinaryWrite
Took me two days.

Resources