download file inside updatepanel with out PostBackTrigger - asp.net

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)

Related

Send Excel file to Browser Asp.net

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:

HTTP/2 Image load times - waiting for the last one to finish

This is baffling me. On a new server (Windows Server 2016) my images seem to be loading in synchronously. The browser is attempting to download them all at the same time, but something is stopping the image from loading until the previous one has finished. The time to first byte increases as each image is attempted to be loaded.
EDIT: I have posted my imagehandler code below, but you can see the problem exists when loading .jpg in its native format (see screenshot about half way down).
EDIT 2: I have disabled http/2 and added a screenshot.
My SVG image handler code (problem exists with image.ashx also):
Dim freshness As TimeSpan = New TimeSpan(1, 0, 0, 0)
Dim now As DateTime = DateTime.Now
Response.Cache.SetExpires(now.Add(freshness))
Response.Cache.SetMaxAge(freshness)
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(True)
Response.Cache.VaryByParams("colour") = True
Response.Cache.VaryByParams("colour2") = True
Response.Cache.VaryByParams("svg") = True
Response.Cache.VaryByParams("rnd") = True
Response.Cache.VaryByHeaders("rnd") = True
Response.Cache.VaryByHeaders("Type") = True
Dim sSVG As String = Request.QueryString("svg").Split("-")(0)
If sSVG = String.Empty Then
Try
sSVG = Request.ServerVariables("SCRIPT_NAME").Split("-")(0)
Catch ex As Exception
sSVG = "svg"
End Try
End If
Dim xDoc As XDocument = XDocument.Load(Server.MapPath("\images\icons\svg\" & sSVG & ".svg"))
Dim sColour As String = "FFFFFF"
Dim sColour2 As String = "FFFFFF"
Dim sXML As String = xDoc.Document.ToString
If Request.QueryString("Colour") <> String.Empty Then
sColour = Request.QueryString("Colour")
Else
Try
sColour = sSVG.Split("-")(1)
Catch ex As Exception
End Try
End If
If Request.QueryString("Colour2") <> String.Empty Then
sColour2 = Request.QueryString("Colour2")
Else
Try
sColour = sSVG.Split("-")(2)
Catch ex As Exception
End Try
End If
sXML = sXML.Replace("COLOUR2", sColour2)
sXML = sXML.Replace("COLOUR", sColour)
Response.Headers.Add("Vary", "Accept-Encoding")
Response.ContentType = "image/svg+xml"
Response.Write(sXML)
HTTP/2 disabled:

Capture response stream and output to file

We are using an online pdf encoding service where we send them the raw html and they return the pdf document. We want to take the WebResponse and immediately download it as a file to their desktop. This seems so straightforward and yet I can't seem to capture the stream correctly for download. I've tried many different approaches but I always end up with a 0 byte file for download. This is my latest incarnation which has gotten overly complicated but it still doesn't work.
Dim request = DirectCast(HttpWebRequest.Create(Url), HttpWebRequest)
request.Method = "POST"
request.ContentType = "application/x-www-form-urlencoded"
request.ContentLength = byteArray.Length
Using dataStream = request.GetRequestStream()
dataStream.Write(byteArray, 0, byteArray.Length)
End Using
Try
Dim response As WebResponse = request.GetResponse
Dim bytes As Byte()
Using st As Stream = response.GetResponseStream
Dim ByteList As New ArrayList
Dim reader As New BinaryReader(st)
Dim length As Integer
While (InlineAssignHelper(bytes, reader.ReadBytes(1024))).Length > 0
ByteList.Add(bytes)
length += bytes.Length
bytes = New Byte(length - 1) {}
Dim position As Integer = 0
For Each b As Byte() In ByteList
Array.Copy(b, 0, bytes, position, b.Length)
position += b.Length
Next
End While
End Using
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.AddHeader("Content-Type", "application/pdf")
HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("{0}; filename=Report Detail.pdf; size={1}", "attachment", bytes.Length.ToString()))
HttpContext.Current.Response.BinaryWrite(bytes)
HttpContext.Current.Response.Flush()
HttpContext.Current.Response.Close()
HttpContext.Current.Response.End()
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
target = value
Return value
End Function

how to display an image from database?

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"/>

ZipOutputStream MemoryLeak

I am using ZipOutputStream to get files from db, compress to zip and download (zip file around 400mb).
During this, my app pool memory is going up to 1.4gb and after download is complete, its coming down to 1gb when it should come back to like 100 mb or something.
There are only like 10 users using this app and only 1 user using this particular page.
i am calling the dispose method. I aslo tried explictly calling GC.Collect but still no use.
Am i missing anything here?
Thanks in advance.
Dim zipStream = New ZipOutputStream(HttpContext.Current.Response.OutputStream)
Try
da.Fill(ds)
For Each dr As DataRow In ds.Tables(0).Rows
Try
Dim docName As String = ""
strImgID = dr("image_id")
If Not IsDBNull(dr("loan_number")) Then iLoanID = dr("loan_number")
If Not IsDBNull(dr("document_name")) Then docName = dr("document_name")
Dim ext As String = dr("image_type_extension")
Dim strFinalFileName As String = ""
strFinalFileName = docName & "_" & iLoanID & ext
Dim b As Byte() = dr("image_binary")
Dim fileEntry = New ZipEntry(Path.GetFileName(strFinalFileName))
zipStream.PutNextEntry(fileEntry)
zipStream.Write(b, 0, b.Length)
Catch ex As Exception
LogError(ex, iLoanID & "," & strImgID)
AddError(sb, ex, iLoanID & "," & strImgID)
End Try
Next
Catch ex As Exception
Throw
Finally
zipStream.Close()
zipStream.Dispose()
cmd.Connection.Close()
cmd.Connection.Dispose()
End Try
You need to chunk data into the stream rather than allocate all at once.
E.g. (in c#)
byte[] buffer = new byte[4096];
FileStream readFs = File.OpenRead(strFile);
for (int rnt = readFs.Read(buffer, 0, buffer.Length);
rnt > 0;
rnt = readFs.Read(buffer, 0, buffer.Length))
{
zipoutputstream.Write(buffer, 0, rnt);
}
I think this will help with your memory issue. Please comment back if not..

Resources