It's been a while since I've been here. I've been working on an ASP project where the attachment is stored to DB. I'm trying to get the bytes stored in the table to a file.
I was able to make the file, however, I couldn't get the bytes from the table.
This is the code that enters the file to the table:
'Saves the upload file data to database for the using Request_ID after the request has been created
strFileName = FileUploadReqDtl.FileName
strFileExt = strFileName.Substring(strFileName.IndexOf(".") + 1)
intFileSize = FileUploadReqDtl.PostedFile.ContentLength()
Dim theDataSize As Byte() = New Byte(FileUploadReqDtl.PostedFile.ContentLength - 1) {}
Dim uploadedFile As HttpPostedFile = FileUploadReqDtl.PostedFile
Dim theData = uploadedFile.InputStream.Read(theDataSize, 0, CInt(FileUploadReqDtl.PostedFile.ContentLength))
I was able to create a link on a page that goes to another ASP page and tries to make the file downloadable. I know that the SQL is working properly to get the records from the table, however, I'm not able to get the bytes properly:
If (dr.HasRows = True) Then
While dr.Read()
' Casting the value returned by the datareader to the byte[] data type.
result = CType(dr.GetValue(0), Byte())
strFileName = dr.GetString(1)
Debug.Write("strFileName: " & strFileName & vbCrLf)
End While
End If
dr.Close()
cnToDb.Close()
ShowFile(strFileName, result, MimeType)
Catch ex As Exception
MsgBox("Uh oh, I couldn't get the attachment!")
Debug.Write("Uh oh, I couldn't get the attachment!")
Debug.Write(ex.Message & " - " & ex.StackTrace & vbCrLf & vbCrLf)
result = Nothing
End Try
This is the ShowFile function which finally "creates the file" with the bytes from the database:
Dim fileData() As Byte
fileData = byteFileData
Response.Clear()
Response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName)
Response.ContentType = MimeType
Response.BinaryWrite(fileData)
Response.End()
Response.Flush()
The exception I'm hitting that I'm having issues with is:
SQL: SELECT Data, FileName FROM tblFileUploadData WHERE Report_ID =
116
strFileName: TheAwesomeAttachment.txt A first chance exception of type
'System.Threading.ThreadAbortException' occurred in mscorlib.dll Uh
oh, I couldn't get the attachment!Thread was being aborted. - at
System.Threading.Thread.AbortInternal() at
System.Threading.Thread.Abort(Object stateInfo) at
System.Web.HttpResponse.End() at
WebApplication3.WebForm2.ShowFile(String strFileName, Byte[]
byteFileData, String MimeType) in C:\Users\Mike\documents\visual
studio
2010\Projects\WebApplication3\WebApplication3\Attachment.aspx.vb:line
81 at WebApplication3.WebForm2.getAttachment(Int32 RequestID,
String MimeType) in C:\Users\Mike\documents\visual studio
2010\Projects\WebApplication3\WebApplication3\Attachment.aspx.vb:line
56
A first chance exception of type
'System.Threading.ThreadAbortException' occurred in
WebApplication3.DLL An exception of type
'System.Threading.ThreadAbortException' occurred in
WebApplication3.DLL but was not handled in user code The thread '<No
Name>' (0x728) has exited with code 0 (0x0). The program '[13512]
WebDev.WebServer40.EXE: Managed (v4.0.30319)' has exited with code 0
(0x0). The program '[13512] WebDev.WebServer40.EXE: Program Trace' has
exited with code 0 (0x0).
Take a look at:
http://support.microsoft.com/kb/312629
"For Response.End, call the HttpContext.Current.ApplicationInstance.CompleteRequest method instead of Response.End to bypass the code execution to the Application_EndRequest event"
I like to create an .ashx file for this type of situation. You can link to it and it will download the file without showing a page.
Public Class DownloadFile
Implements System.Web.IHttpHandler
Public Sub ProcessRequest(context As HttpContext) Implements IHttpHandler.ProcessRequest
Try
Dim id As String = context.Request.QueryString("id")
Dim filename As String = ""
Dim output As Byte()
filename = ServiceHelper.GetFilenameByID(id)
output = ServiceHelper.GetFileBytesByID(id)
Dim ext As String = System.IO.Path.GetExtension(filename)
Dim contenttype As String
'clear the current output content from the buffer
context.Response.Clear()
'add the header that specifies the default filename for the
'Download/SaveAs dialog
context.Response.AddHeader("Content-Disposition", "attachment; filename=" & filename)
'add the header that specifies the file size, so that the browser
'can show the download progress
context.Response.AddHeader("Content-Length", output.Length.ToString())
'specify that the response is a stream that cannot be read by the
'client and must be downloaded
'Response.ContentType = "application/octet-stream"
context.Response.Buffer = True
Select Case ext
Case ".doc"
contenttype = "msword"
Case ".pdf"
contenttype = "pdf"
Case ".xls"
contenttype = "x-excel"
Case ".ppt"
contenttype = "ms-powerpoint"
Case Else
contenttype = "octet-stream"
End Select
context.Response.ContentType = "application/" & contenttype
context.Response.BinaryWrite(output)
'http://support.microsoft.com/kb/312629
'context.Response.End()
context.ApplicationInstance.CompleteRequest()
Catch
End Try
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Related
I'm trying to download an XML file, the file already exists in the specified path, I am not familiar with VB and probably this code is not right, I need help just in it to be able to download an existing xml file, here's the code:
Protected Sub DownloadFile(ByVal sPath As String)
Dim TargetFile As New System.IO.FileInfo(sPath)
Response.Clear()
Response.AddHeader("Content-Disposition", "attachment; filename=" +
TargetFile.Name)
Response.AddHeader("Content-Length", TargetFile.Length.ToString())
Response.ContentType = "text/xml"
Response.WriteFile(TargetFile.FullName)
Response.End()
End Sub
The error returned in the console:
Uncaught Error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Contextualizing the problem:
I have serialized an object and created an XML file, then I would simply like to download this file, my difficulty is to download the file.
Dim oObj1 As New System.Xml.Serialization.XmlSerializer(GetType(eSocial.Eventos.evtTabHorTur.eSocial))
Dim sFileName = Date.Now.ToString("yyyyMMddHHmmss") & ".xml"
Dim sPath = Constantes.Ambiente.CaminhoSite & "temp\" & sFileName
Dim oFile As New System.IO.StreamWriter(sPath)
oObj1.Serialize(oFile, eSocialCamposXml)
oFile.Close()
You are saying you are having difficulty downloading but there is nothing in the code except showing writing a file and then serializing a file. You would be using a 'StreamReader' or similar manner to READ a file. Here is a simple example. Say I have an xml structure on a file location with the schema like:
<root>
<test>Data</test>
</root>
I could write this in VB.NET to get it:
Sub Main()
Dim xmlFile As XDocument
Dim fileLocation = "D:\\Test Code\\Test.xml"
Using sr = New StreamReader(fileLocation)
xmlFile = XDocument.Parse(sr.ReadToEnd())
End Using
Console.WriteLine(xmlFile.Root.Element("test").Value.ToString)
Console.ReadLine()
End Sub
I have found good information on how to automatically download a file to the client advertised as a solution of how to print using code
(https://forums.asp.net/t/1233841.aspx?How+do+I+print+from+Reporting+Services+AUTOMATICALLY+in+VB+Net+web+app+)
but what I need to do is have the code print the document without the user interacting.
From what I have found it appears this can not be done as one might casually think. ReportViewer for example does not have a 'print' method.
The only two solutions appears to be to use ProcessStart (which then means saving the file to the file system before printing which I dont want to do)
or maybe (will be researching this today) create a subscription using code and then delete it later.
You are not able to print a report directly from your asp.net page. The reason for this is security. If it allowed you to send a file through the network and onto the clients computer, and then search the computer for a printer, this could cause major security issues. The report viewer does have a print icon, but this disappears when you deploy the project and run the page remotely. I have faced the same issue in the past and found it best to just export the report to say PDF and allow the user to Download it. I have used the below code to accomplish this task in the past:
Private Sub CreatePDFMatrix(fileName As String)
' ReportViewer1.LocalReport.DataSources.Clear()
Dim adapter As New ReportDataSetTableAdapters.vwPrintTagsTableAdapter
Dim table As New ReportDataSet.vwPrintTagsDataTable
Dim month = MonthName(Date.Today.Month)
Dim year = Date.Today.Year
Dim p(1) As ReportParameter
Dim warnings() As Warning
Dim streamIds As String()
Dim mimeType As String = String.Empty
Dim encoding As String = String.Empty
Dim extension As String = String.Empty
Dim adpt2 As New ReportDataSetTableAdapters.vwPrintTagsTableAdapter
adapter.FillForMainReport(table, DropDownList1.SelectedValue, g_Company, g_Division)
Me.ReportViewer1.LocalReport.DataSources.Add(New ReportDataSource("DataSet1", CType(table, DataTable))) 'Add(New ReportDataSource("ReportingData", CType(table, DataTable)))
Me.ReportViewer1.DataBind()
Dim viewer = ReportViewer1
viewer.ProcessingMode = ProcessingMode.Local
viewer.LocalReport.ReportPath = "Report1.rdlc"
p(0) = New ReportParameter("MonthYear", month & "-" & year)
Dim check = DropDownList1.SelectedValue
ReportViewer1.LocalReport.SetParameters(p(0))
p(1) = New ReportParameter("Location", DropDownList1.SelectedValue)
ReportViewer1.LocalReport.SetParameters(p(1))
Try
Dim bytes As Byte() = viewer.LocalReport.Render("PDF", Nothing, mimeType, encoding, ".pdf", streamIds, warnings)
Response.Buffer = True
Response.Clear()
Response.ContentType = mimeType
Response.AddHeader("content-disposition", Convert.ToString((Convert.ToString("attachment; filename=") & fileName) + ".") & extension)
Response.BinaryWrite(bytes)
' create the file
Response.Flush()
Catch ex As Exception
Debug.Print(ex.ToString)
End Try
End Sub
I'm developing a asp.net webforms website using vb.net. In that list of files displayed in a gridview as links, when clicked on a link it calls OpenFile method. This code I found on the web is used to download file stored in webserver to client, this works fine for images but when I try to download .docx or .xlsx file it gives an error
in the line "Response.BinaryWrite(btFile)", but downloads the file. Given below is shortend version of the actual code
Page Code:
Protected Sub grvItemAttachments_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles grvItemAttachments.RowCommand
Try
If e.CommandName = "Open" Then
FileOpener.OpenFile(fileNameWithPath)
End If
Catch ex As Exception
ErrHandler.WriteError(ex.Message)
End Try
End Sub
File Opener Code:
Public Shared Sub OpenFile(fileNameWithPath as string)
Dim file As New FileInfo(fileNameWithPath)
Dim fs As System.IO.FileStream = Nothing
fs = System.IO.File.Open(fileNameWithPath, System.IO.FileMode.Open)
Dim btFile As Byte() = New Byte(fs.Length - 1) {}
fs.Read(btFile, 0, Convert.ToInt32(fs.Length))
fs.Close()
Response.AddHeader("Content-disposition", "attachment; filename=" & FileName)
Response.ContentType = GetFileType(file.Extension.ToLower())
Response.BinaryWrite(btFile)
Response.End()
End Sub
Error Message:
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values." & vbCrLf & "Parameter name: offset" & vbCrLf & " at System.Web.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count)" & vbCrLf & " at System.Web.HttpResponse.BinaryWrite(Byte[] buffer)" & vbCrLf & " at FileOpener.OpenFile(String FileName, String FolderName) in D:\Projects\VSS Projects\PIL WebSite\App_Code\Common\FileOpener.vb:line 25" & vbCrLf & " at Web_RTOView.grvItemAttachments_RowCommand(Object sender, GridViewCommandEventArgs e) in D:\Projects\VSS Projects\PIL WebSite\Web\RTOView.aspx.vb:line 310}
------
grvItemAttachments_RowCommand
Error Message: Specified argument was out of the range of valid values.
Parameter name: offset
Any idea how to solve this issue?
Why are you initializing your byte array to Length-1? Shouldn't it be exact size as Length?
In fact, you try to read the contents of the file from 0 to Length but your byte array length is Length-1
I am having an issue with my ASHX handler that is generating PDF.
When the user hits a "View PDF" button, it will look in the database for the PDF file and display it, but if there isn't a PDF file there it should display a blank page saying "no PDF available", but instead I get a "null reference" error on this line of code:
ms.WriteTo(context.Response.OutputStream)
Below is the code for the handler:
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
'This class takes the uniqueidentifier of an image stored in the SQL DB and sends it to the output stream
'This saves storing copies of image files on the web server as well as in the DB
context.Response.Clear()
If context.Request.QueryString("fileSurveyID") IsNot Nothing Then
Dim filesID As String = context.Request.QueryString("fileSurveyID")
Dim fileName = String.Empty
Dim ms As MemoryStream = GetPDFFile(filesID)
context.Response.ContentType = "application/pdf"
context.Response.AddHeader("Content-Disposition", "attachment;filename=" & fileName)
context.Response.Buffer = True
ms.WriteTo(context.Response.OutputStream)
context.Response.End()
Else
context.Response.Write("<p>No pdf file</p>")
End If
End Sub
Can anyone tell me how to get rid of this error?
Simple If..Then should do the trick:
Dim ms As MemoryStream = GetPDFFile(filesID)
If ms IsNot Nothing Then
context.Response.ContentType = "application/pdf"
context.Response.AddHeader("Content-Disposition", "attachment;filename=" & fileName)
context.Response.Buffer = True
ms.WriteTo(context.Response.OutputStream)
context.Response.End()
End If
You probably want to move the following out of the if:
context.Response.End()
so it execute each time regardless.
However you say the following line executes when no PDF available:
ms.WriteTo(context.Response.OutputStream)
which would suggest something wrong with your if condition
Here's my agonizing problem. I'm transferring from one FTP (a Dev site) to another FTP (a Test site). Spare me the thoughts of changing this process. It's out of my hands. In any case, here's my method:
Public Function TransferFile(originalFile As String, destinationFile As String) As String
Try
'FileStream for holding the file
Dim uploadRequest As FtpWebRequest = WebRequest.Create(destinationFile)
uploadRequest.Method = WebRequestMethods.Ftp.UploadFile
uploadRequest.Credentials = New NetworkCredential(ftp_user, ftp_pw)
uploadRequest.UseBinary = True
uploadRequest.UsePassive = False
'connect to the server
Dim fileRequest As FtpWebRequest = WebRequest.Create(originalFile)
fileRequest.Method = WebRequestMethods.Ftp.DownloadFile
fileRequest.Credentials = New NetworkCredential(ftp_user, ftp_pw)
fileRequest.UseBinary = True
fileRequest.UsePassive = False
'get the servers response
Dim response As WebResponse = fileRequest.GetResponse()
'retrieve the response stream
Dim stream As Stream = response.GetResponseStream()
CopyStream(stream, uploadRequest.GetRequestStream)
stream.Close()
response.Close()
Return "File transfered"
Catch ex As System.Security.SecurityException
Return ex.Message
Catch ex As Exception
Return ex.Message
End Try
End Function
Public Shared Sub CopyStream(input As Stream, output As Stream)
Dim buffer As Byte() = New Byte(32767) {}
While True
Dim read As Integer = input.Read(buffer, 0, buffer.Length)
If read <= 0 Then
Return
End If
output.Write(buffer, 0, read)
End While
End Sub
This works perfectly for ASPX files and their .vb code behinds. When we try to transfer .DLL files, they show up on the server as 0 bytes, and sometimes actually transfer. The problem is that, despite being the same size as the original, they act as if they are corrupt. Does anyone have a solution?
Just a guess - use BYREF in your sub definition
Public Shared Sub CopyStream(BYREF input As Stream, BYREF output As Stream)
Closing out the output stream and getting a response from the uploadRequest worked.