I have been breaking my head for the last two days and can't get this to work. I have a report, which I am exporting to Excel and saving on the server file directory. That part works perfectly, I can see the file, and open it, all good. The issue relies on when I try to send it to the browser for download from the server. It does not download anything, I do see the Response Header with all the info on the browser but nothing happens.
Here's one of my many tries
Private Sub dxgvPOAll_ToolbarItemClick(source As Object, e As ASPxGridViewToolbarItemClickEventArgs) Handles dxgvPOAll.ToolbarItemClick
Select Case e.Item.Name
Case "ExportAll"
Using report As DevExpress.XtraReports.UI.XtraReport = New POs_Dashboard_Report()
Using ms As New System.IO.MemoryStream()
report.Name = "Backorder Tickets"
report.ExportOptions.PrintPreview.SaveMode = DevExpress.XtraPrinting.SaveMode.UsingSaveFileDialog
Dim xlsxExportOptions As New DevExpress.XtraPrinting.XlsxExportOptions() With {.ExportMode = DevExpress.XtraPrinting.XlsxExportMode.SingleFile, .ShowGridLines = True, .FitToPrintedPageHeight = True}
Dim folderPath As String = "~/Account/TemporaryFiles/" & Utilities.RetrieveEmployeeNumber() & "/" & Guid.NewGuid.ToString & "/"
Dim serverPath As String = Server.MapPath(folderPath)
Dim xlsxExportFilePath As String = serverPath & report.Name & ".xlsx"
Dim folderInf As New DirectoryInfo(serverPath)
If Not folderInf.Exists Then folderInf.Create()
report.ExportToXlsx(xlsxExportFilePath, xlsxExportOptions)
Try
Dim objRequest As FileWebRequest = CType(WebRequest.Create(xlsxExportFilePath), FileWebRequest)
Dim objResponse As FileWebResponse = CType(objRequest.GetResponse(), FileWebResponse)
Dim bufferSize As Integer = 1
Response.Clear()
Response.ClearHeaders()
Response.ClearContent()
Response.AppendHeader("Content-Disposition:", "attachment; filename=" & xlsxExportFilePath)
Response.AppendHeader("Content-Length", objResponse.ContentLength.ToString())
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Dim byteBuffer As Byte() = New Byte(bufferSize + 1 - 1) {}
Dim memStrm As MemoryStream = New MemoryStream(byteBuffer, True)
Dim strm As Stream = objRequest.GetResponse().GetResponseStream()
Dim bytes As Byte() = New Byte(bufferSize + 1 - 1) {}
While strm.Read(byteBuffer, 0, byteBuffer.Length) > 0
Response.BinaryWrite(memStrm.ToArray())
Response.Flush()
End While
HttpContext.Current.Response.Flush()
HttpContext.Current.Response.SuppressContent = True
HttpContext.Current.ApplicationInstance.CompleteRequest()
Catch e1 As ThreadAbortException
Catch ex As Exception
End Try
End Using
End Using
End Select
End Sub
Here's what I see on the browser's Response-Header:
Related
I am using this part of code to download file using the onClick event for imageButton inside UpdatePanel, it works fine if I add the imageButton as PostBackTrigger for the updatePanel, is there away to do that with out full postback?
Dim stream As IO.Stream = Nothing
Dim bytesToRead As Integer = 10000
Dim buffer As Byte() = New Byte(bytesToRead - 1) {}
Try
Dim fileReq As Net.HttpWebRequest = CType(Net.HttpWebRequest.Create(FileURL), Net.HttpWebRequest)
Dim fileResp As Net.HttpWebResponse = CType(fileReq.GetResponse(), Net.HttpWebResponse)
If fileReq.ContentLength > 0 Then fileResp.ContentLength = fileReq.ContentLength
stream = fileResp.GetResponseStream()
Dim resp = HttpContext.Current.Response
resp.ContentType = "application/octet-stream"
resp.AddHeader("Content-Disposition", "attachment; filename=""" & FileName & """")
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString())
Dim length As Integer
Do
If resp.IsClientConnected Then
length = stream.Read(buffer, 0, bytesToRead)
resp.OutputStream.Write(buffer, 0, length)
resp.Flush()
buffer = New Byte(bytesToRead - 1) {}
Else
length = -1
End If
Loop While length > 0
Finally
If stream IsNot Nothing Then
stream.Close()
End If
End Try
I found the solution.
#HATCHA's answer on Asp:progress won't end anitmation when file is downloaded from ashx file was great.
what #VDWWD said was wonderful , But not in my case, because I need a button to create the pdf file before starting the download. which means the client side click won't be useful.
ScriptManager.RegisterClientScriptBlock(Me, GetType(Page), "downloadFileExport", "javascript:window.location ='" & ResolveUrl("~/report/download.ashx?url=" & url & "&fName=" & fName) & "';", True)
Try
'connection string
Dim dbpath As String = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
dbpath = New Uri(dbpath).LocalPath
Dim my_connection As String = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=D:\DataBase\KhandagramPS.mdb"
Dim userTables As DataTable = Nothing
Dim connection As System.Data.OleDb.OleDbConnection = New System.Data.OleDb.OleDbConnection()
Dim DR As OleDbDataReader
'Dim source As String
'query string
Dim my_query As String = "SELECT sl_no,f_name,dob,sex,add,reg,[class],a_date,a_per,r_a_per,f_status,[name],photo,document FROM " & TextBox2.Text & " where sl_no=" & TextBox3.Text & " ;"
'create a connection
Dim my_dbConnection As New OleDbConnection(my_connection)
my_dbConnection.Open()
'create a command
Dim my_Command As New OleDbCommand(my_query, my_dbConnection)
DR = my_Command.ExecuteReader()
While (DR.Read())
txtslno.Text = (DR(0).ToString())
txtfname.Text = (DR(1).ToString())
Date1.Text = (DR(2).ToString())
comsex.Text = (DR(3).ToString())
txtadd.Text = (DR(4).ToString())
txtreg.Text = (DR(5).ToString())
comclass.Text = (DR(6).ToString())
Date2.Text = (DR(7).ToString())
txtaper.Text = (DR(8).ToString())
txtraper.Text = (DR(9).ToString())
txtfstatus.Text = (DR(10).ToString())
txtname.Text = (DR(11).ToString())
Dim ImageBuffer = CType(DR(12), Byte())
Dim imgStrm As New MemoryStream(ImageBuffer, True)
imgStrm.Write(ImageBuffer, 0, ImageBuffer.Length)
Dim img As Image = Image.FromStream(imgStrm)
PictureBox1.Image = img
End While
'close connection
my_dbConnection.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
I suspect some error in your Byte-Array to Image conversion. Make sure that your Byte-Array is not messed up. Use this function instead.
Private Function getImage(imageBuffer as Byte())
Using ms as new IO.MemoryStream(imageBuffer)
Dim img = ImageIO.FromStream(ms)
Return img
End Using
End Function
my 2 cents: you shouldn't store images in an mdb file (unless things have changed a lot in the past few years). store images in a separate directory and store the file paths in the mdb so the image can be found when needed.
I know this has been answered on here and a thousand other sites on the web, but every single one I've tried does not work as I want it to. I want to export ONLY a datatable, not the page I'm running the code from, and I want to do this without having to download a 3rd party dll. Every piece of code I've tried ends up exporting the page I'm running it from. Here's the current iteration I'm using...
Private Sub ExporttoExcel(table As DataTable)
Dim attachment As String = "attachment; filename=file.xls"
Response.ClearContent()
Response.AddHeader("content-disposition", attachment)
Response.ContentType = "application/vnd.ms-excel"
Dim tab As String = ""
For Each dc As DataColumn In table.Columns
Response.Write(tab + dc.ColumnName)
tab = vbTab
Next
Response.Write(vbLf)
Dim i As Integer
For Each dr As DataRow In table.Rows
tab = ""
For i = 0 To table.Columns.Count - 1
Response.Write(tab & dr(i).ToString())
tab = vbTab
Next
Response.Write(vbLf)
Next
Response.End()
End Sub
Can anyone explain why this doesn't work or how I can export ONLY the datatable into Excel?
I usually do this and it has worked for me (ds is a DataSet which has the data I want to push to excel):
HttpResponse response = HttpContext.Current.Response;
// first let's clean up the response.object
response.Clear();
response.Charset = "";
string filename = "TEMP/ex1.xls";
// set the response mime type for excel
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
// create a string writer
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// instantiate a datagrid
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables[0];
dg.DataBind();
dg.RenderControl(htw);
response.Write(sw.ToString());
response.End();
}
}
this should work with EPPlus
Public Shared Function ExportToExcel(FileName As String, SheetName As String, data As DataTable) As Boolean
Dim pck As ExcelPackage
pck = New ExcelPackage()
Try
Dim ws = pck.Workbook.Worksheets.Add(SheetName)
ws.Cells("A1").LoadFromDataTable(data, True)
Dim excel = pck.GetAsByteArray()
HttpContext.Current.Response.ClearHeaders()
HttpContext.Current.Response.ClearContent()
HttpContext.Current.Response.Clear() 'really clear it :-p
HttpContext.Current.Response.BufferOutput = False
HttpContext.Current.Response.ContentType = "application/octet-stream"
HttpContext.Current.Response.AddHeader("cache-control", "max-age=0")
HttpContext.Current.Response.AddHeader("Pragma", "public")
HttpContext.Current.Response.AddHeader("Content-Length", excel.Length.ToString())
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=""" & FileName & ".xlsx""")
HttpContext.Current.Response.BinaryWrite(excel)
HttpContext.Current.Response.[End]()
Return True
Catch
Return False
Finally
pck.Dispose()
End Try
End Function
The only way to do this without some kind of 3rd party dll is to write a csv file.
Columns separated by semicolon, rows separated by /n
i know too that this (kind of) question has been asked and answered many times. I myself have asked this once before. But I havnt been successful yet. how do I display the image in an image control for a particular employee ID... Heres my code:
`
bind()
GridView1.Visible = "True"
Dim strQuery As String = "SELECT Image FROM EmployeeTable WHERE EmployeeID =#EmployeeID"
Dim cmd As SqlCommand = New SqlCommand(strQuery)
cmd.Parameters.Add("#EmployeeID", SqlDbType.Int).Value() = Convert.ToInt32(Request.QueryString("ImageID"))
Dim dt As DataTable = GetData(cmd)
If dt IsNot Nothing Then
**Dim bytes() As Byte = CType(dt.Rows(1)("Image"), Byte())**
Response.Buffer = True
Response.Charset = ""
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = dt.Rows(0)("ContentType").ToString()
Response.AddHeader("content-disposition", "attachment;filename=" + dt.Rows(1)("Name").ToString())
Response.BinaryWrite(bytes)
Response.Flush()
Response.End()
End If`
Getting error at the line in bold. "There is no row at position 1"...
Actually I want to fetch (display) the image for a particular employee id. How does it concern a row position? I dont know why i have written that line of code. Anyway, I know there are guys who can help me with this and so I thank them in advance...
OK, Heres my code for adding the image to the database. This is working fine.
Dim imageData As Byte() = New Byte(FileUpload1.FileContent.Length) {}
FileUpload1.FileContent.Read(imageData, 0, Convert.ToInt32(FileUpload1.FileContent.Length))
Dim con As New SqlConnection(System.Configuration.ConfigurationManager.AppSettings("ConnectionString").ToString)
con.Open()
If EmployeeIDTextBox.Text = "" Then
MsgBox("Please Enter EmployeeID to Add Photo")
Else
Dim com As New SqlCommand("UPDATE EmployeeTable SET IMAGE = #IM where EmployeeID='" & EmployeeIDTextBox.Text & "'", con)
Dim filePath As String = Server.MapPath(FileUpload1.FileName)
'Dim imageData As Byte() = File.ReadAllBytes(filePath)
com.Parameters.AddWithValue("#IM", imageData)
com.ExecuteNonQuery()
MsgBox("File Saved Successfully!")
End If
End Sub
And now this is my code for retrieving & displaying the same image in an image control...
bind()
GridView1.Visible = "True"
'If Request.QueryString("ImageID") IsNot Nothing Then
Dim strQuery As String = "SELECT Image FROM EmployeeTable WHERE EmployeeID =#EmployeeID"
Dim cmd As SqlCommand = New SqlCommand(strQuery)
cmd.Parameters.Add("#EmployeeID", SqlDbType.Int).Value() = Convert.ToInt32(Request.QueryString("Image"))
Dim dt As DataTable = GetData(cmd)
If dt IsNot Nothing Then
Dim bytes() As Byte = CType(dt.Rows(0)("Image"), Byte())
Response.Buffer = True
Response.Charset = ""
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = dt.Rows(0)("ContentType").ToString()
Response.AddHeader("content-disposition", "attachment;filename=" + dt.Rows(1)("Name").ToString())
Response.BinaryWrite(bytes)
Response.Flush()
Response.End()
End IF
This is not working...
Array indexes start from 0
Use
Dim bytes() As Byte = CType(dt.Rows(0)("Image"), Byte())
How is it that you don't know why you have written that?
The code you have will prompt a user to save the image file on his pc.
It will not show the image in an image control.
U can use a Http Handler and use the below code in ProcessRequest()
int Id = Convert.ToInt32(Request.QueryString["ImgId"]);
using (var conn = new SqlConnection(connectionString))
using (var command = new SqlCommand(
"SELECT ImageFile FROM ImageTable WHERE ImageId = #ImgId", conn))
{
command.Parameters.Add("#ImgId", SqlDbType.Int).Value = Id ;
conn.Open();
Response.ContentType = "image/gif"; //u can set it per ur requirement
Response.BinaryWrite((byte[]) command.ExecuteScalar());
}
and then use image in your page as :
<asp:Image id="Img_Db" runat="server" ImageUrl="Image.ashx?ImgId=1"/>
I'm having problems with an Invalid Cast Exception when I try and read a PDF from a database as a BLOB. I am able to write the files into the database no problems at all, however, when I try to retrieve them I just get InvalidCastException.
Here is the code I'm using:
Protected Sub btnPDF_Click(sender As Object, e As EventArgs) Handles btnPDF.Click
' Request.QueryString["docid"].ToString();
Dim docuid As String = "b39a443d-ccfd-47f4-b333-f12cd94683d6"
'Connection and Parameters
Dim param As SqlParameter = Nothing
Dim conn As SqlConnection = New SqlConnection(
ConfigurationManager.ConnectionStrings("menu").ToString())
Dim cmd As New SqlCommand("sp_getdoc", conn)
cmd.CommandType = CommandType.StoredProcedure
param = New SqlParameter("#docuid", SqlDbType.NVarChar, 100)
param.Direction = ParameterDirection.Input
param.Value = docuid
cmd.Parameters.Add(param)
'Open connection and fetch the data with reader
conn.Open()
Dim reader As SqlDataReader =
cmd.ExecuteReader(CommandBehavior.CloseConnection)
If reader.HasRows Then
reader.Read()
'
Dim doctype As String = reader("doctype").ToString()
Dim docname As String = reader("docname").ToString()
'
Response.Buffer = False
Response.ClearHeaders()
Response.ContentType = doctype
Response.AddHeader("Content-Disposition",
"attachment; filename=" + docname)
'
'Code for streaming the object while writing
Const ChunkSize As Integer = 1024
Dim buffer() As Byte = New Byte(ChunkSize) {}
Dim binary(reader("document")) As Byte
Dim ms As New MemoryStream(binary)
Dim SizeToWrite As Integer = ChunkSize
For i As Integer = 0 To binary.GetUpperBound(0) - 1 Step i = i + ChunkSize
If Not Response.IsClientConnected Then
Return
End If
If i + ChunkSize >= binary.Length Then
SizeToWrite = binary.Length - i
End If
Dim chunk(SizeToWrite) As Byte
ms.Read(chunk, 0, SizeToWrite)
Response.BinaryWrite(chunk)
Response.Flush()
Next
Response.Close()
End If
End Sub
I am encountering the problem specifically on the following line:
Dim binary(reader("document")) As Byte
It seems to think that binary is being passed an Integer. Is this something to do with the SQLReader? I'm not really sure at this point what the problem is.
Any help would be greatly appreciated.
Many Thanks,
Richard E Logan-Baker
*UPDATE*
I have since worked out the problem that I'm getting by changing the lines to:
Dim blob() As Byte
blob = reader.Item("document")
However, the PDF does not display inside firefox, and when I save the file (even though my DB is only 2MB~) it is quite happy at downloading over 40MB of data! Also, the file size reports as unknown. I am really stuck now.
*UPDATE*
I've now got the PDF to open in the browser, but there is no data being displayed and Adobe Acrobat says it has problems extracting the text/fonts from the file and that the PDF is broken somehow.
Here is my updated code now:
Protected Sub btnPDF_Click(sender As Object, e As EventArgs) Handles btnPDF.Click
' Request.QueryString["docid"].ToString();
Dim docuid As String = "ba32bf45-1b5c-451a-969c-290dc2cf9073"
'Connection and Parameters
Dim param As SqlParameter = Nothing
Dim conn As SqlConnection = New SqlConnection(
ConfigurationManager.ConnectionStrings("menu").ToString())
Dim cmd As New SqlCommand("sp_getdoc", conn)
cmd.CommandType = CommandType.StoredProcedure
param = New SqlParameter("#docuid", SqlDbType.NVarChar, 100)
param.Direction = ParameterDirection.Input
param.Value = docuid
cmd.Parameters.Add(param)
'Open connection and fetch the data with reader
conn.Open()
Dim reader As SqlDataReader =
cmd.ExecuteReader(CommandBehavior.CloseConnection)
If reader.HasRows Then
reader.Read()
'
Dim doctype As String = reader("doctype").ToString()
Dim docname As String = reader("docname").ToString()
'
Response.Buffer = False
Response.ClearHeaders()
Response.ContentType = doctype
Response.AddHeader("Content-Disposition",
"attachment; filename=" + docname)
'
'Code for streaming the object while writing
Const ChunkSize As Integer = 1024
Dim buffer() As Byte = New Byte(ChunkSize) {}
Dim blob() As Byte
blob = reader.Item("document")
Dim ms As New MemoryStream(blob)
Dim SizeToWrite As Integer = ChunkSize
For i As Integer = 0 To blob.GetUpperBound(0) - 1
If Not Response.IsClientConnected Then
Return
End If
If i + ChunkSize >= blob.Length Then
SizeToWrite = blob.Length - i
End If
Dim chunk(SizeToWrite) As Byte
ms.Read(chunk, 0, SizeToWrite)
Response.BinaryWrite(chunk)
Response.Flush()
i = i + ChunkSize
Next i
Response.Close()
End If
End Sub
I think your problem is coming from the way you are incrementing "i" inside the loop. After you increment it by the ChunkSize at the end of your For...Next statement, the "Next i" statement will increment it by 1 again. Try changing that line to:
i = i + ChunkSize - 1
Or alternatively you could add a "Step ChunkSize" at the end of the For statement and remove the line I'm referring to.