File fetch from database using asp - asp-classic

I am storing some the binary data for some files in a database (yes, I know this can be a bad idea). I am able to get the files out, with the correct content type, since I have stored it. But I'm having trouble getting the file to the client with the right filename. Right now I have the following code in a file called get_file.asp:
sSQL = "SELECT filename, contenttype, binarydata FROM new_attachment WHERE filename = '" & filename & "'"
oRs.Open sSQL, conn, 3, 3
If Not oRs.EOF Then
Response.ContentType = oRs(1)
Response.BinaryWrite oRs(2)
End if
This will return files correctly, but with the filename of 'get_file.asp', instead of, say, 'myfile.txt'. The url visited is .../get_file.asp?filename=myfile.txt.
Is there a way I could change the name of the file when the browsers prompts the user to save it somewhere?

You need to send out the correct header:
Response.ContentType = "text/html"
Response.AddHeader "Content-Disposition", "attachment; filename=YOURFILE.TXT"

You need to add a Content-Disposition header.
The header should look like this:
Content-Disposition: attachment; filename=<name of file>
Side note: The way you are concatenating SQL is open to SQL Injection - you should be using parameters.

Related

download server generated file (.vcf)

i have an interactive aspx dialog with some address data (like name, email, address,...). Now i want the user to be able by clicking a button to download the address data as vcf file.
Now, generating the vcf compatible string isn't the problem. But saving it to the client is.
While it returns the vcf string just fine, it does not open a "Save AS"-dialog. Below i attached my logic for the file download.
What am i doing wrong?
(Maybe it's worth mentioning that the code-behind function calls come from java script,...)
Thanks for any helpfull answers in advance.
Public Sub SaveText(ByVal Text As String)
Dim FileName As String = System.IO.Path.GetRandomFileName()
Using sw As New System.IO.StreamWriter(Server.MapPath(FileName + ".txt"))
sw.WriteLine(Text)
sw.Close()
End Using
Dim fs As System.IO.FileStream = Nothing
fs = System.IO.File.Open(Server.MapPath(FileName + ".txt"), System.IO.FileMode.Open)
Dim btFile(fs.Length) As Byte
fs.Read(btFile, 0, fs.Length)
fs.Close()
With HttpContext.Current.Response
.Clear()
.Buffer = True
.Expires = 0
.AddHeader("Content-disposition", "attachment;filename=" + FileName)
.AddHeader("Content-Length", btFile.Length.ToString)
.ContentType = "application/octet-stream"
.BinaryWrite(btFile)
'.OutputStream.Write(btFile, 0, btFile.Length())
.Flush()
.End()
End With
End Sub
Ok, the problem was not the above mentioned logic itself. The way i handeled the response on the client side was just wrong. The calling java script function expected something else.
I would elaborate in more detail, but this stuff here is so home grown and proprietary, it wouldn't make any sense.
Cheers.

set default name to PDF document with itextsharp

i am sending a PDF to my page and i want to set a default name when the user tries to save the PDF document.
i am using ItextSharp and VB.Net
Using s As MemoryStream = New MemoryStream()
Dim Pdf_Writer As PdfWriter = PdfWriter.GetInstance(DocumentPDF, s)
DocumentPDF.Open()
DocumentPDF.SetMargins(10.0F, 10.0F, 10.0F, 10.0F)
DocumentPDF.Add(Table)
DocumentPDF.Close()
contentX= s.ToArray()
HttpContext.Current.Response.Buffer = False
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.ClearContent()
HttpContext.Current.Response.ClearHeaders()
HttpContext.Current.Response.ContentType = "Application/pdf"
HttpContext.Current.Response.BinaryWrite(contentX)
HttpContext.Current.Response.Flush()
HttpContext.Current.Response.End()
End Using
.
Response.AddHeader("content-disposition", #"attachment;filename=""MyFile.pdf""");
this way download the file(yea, it sets a default name), but i just want to show the file and if the user wants to save it, well... save it(with a default name)
how can i set a default name to my PDF document?
try with this code:
Response.ContentType = "application/pdf"
Response.AppendHeader("Content-Disposition", "inline; filename="filename".pdf")
Response.TransmitFile("filename")
Response.End()
I had a similar problem delivering a PDF via a handler page (.ashx). No matter what I set in the HTTP headers, saving from the browser PDF reader would always set the filename to "getpdf.pdf" when I used this url.
http://www.thepdfchef.com/handlers/getpdf.ashx?id=5188p
So what I did was add an escaped string after the handler path then the querystring at the end of that, like so:
http://www.thepdfchef.com/handlers/getpdf.ashx/Wellbeing%20And%20Domestic%20Assistance%20From%20John%20Paul?id=5188p
You should check for invalid characters and strip out any that could cause the name to be dangerous.

determine content-length of html string

I am exporting a HTML table to excel by sending the data as a HTML Table string and setting the content headers:
Dim html as String = "<table><tr><td>example<td></tr></table>"
context.Response.Clear()
context.Response.AddHeader("Content-Disposition", "attachment; filename=" & "exceldata-" & Now.ToString("yyyyMMddHHmmss") & ".xls")
'context.Response.AddHeader("Content-Length", ????)
context.Response.ContentType = "application/octet-stream"
context.Response.Write(response)
context.Response.End()
Is there a simple way of setting the content-length based on the size of the html string? Or should I just leave it blank anyway...would be nice to have the content-length ideally...
I am returning this using a GenericHandler in asp.net
Replace with the encoding of your choice, probably UTF8. Sorry for the C#:
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytes = encoding.GetBytes(html);
int length = bytes.Length;
Source: http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.contentlength.aspx
This seems too easy, but is it not just equal to html.Length?
I haven't used ASP.NET, but I guess that the Length() method returns the length of the string in chars, not bytes, so it won't work if your server uses UTF-8 or Unicode for serving the pages.
As noted in another answer, just let the server fill it for you. If you think about it, you don't have to add it when you generate HTML pages from ASP since the web server would generate it based in the response from the ASP module.

ASP.NET Filename encoding while sending file

I am sending a file from ASP.NET Page to the browser. To properly send a filename I am adding a header:
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
The problem is that when file contains white spaces (e.g. "abc def") browser receives only "abc" part of the filename. I have tried with: Server.HtmlEncode but it didn't help.
Do you have any idea how to solve this problem?
PK
Put the file name in quotes:-
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
Don't UrlEncode. This is not the right way to escape a value for use in an HTTP structured header parameter. It only works in IE due to that browser's buggy handling, and even then not reliably.
For a space you can use a quoted-string as suggested by Anthony (+1). But the dirty truth of Content-Disposition is that there is no reliable, supported escaping scheme that can be used to put arbitrary characters such as ;, " or Unicode characters in the filename parameter. The only approach that works reliably cross-browser is to drop the filename parameter completely and put the desired filename in the URI as a trailing, UTF-8+URL-encoded path part.
See this answer for some background.
Filename with special symbols(e.g: space; # # ! $ ) or Non-Unicode characters either cannot be supported by some browsers or cause incorrect filename in client machine.
Here is an article by a Chinese called chanext, he gave a perfect way to solve this problem:
this article gave a sample code(written with c#) to show how to get perfect solution to this problem in the all four popular browsers (IE; Opera; Firefox and Chrome)
the filename "Microsoft.Asp.Net.doc" and "F ile;;!#%#^&y.doc" can both be output correctly using the way the author provided in this article.
http://ciznx.com/post/aspnetstreamdownloaddisplaynonunicodespacechar.aspx
Based on the code referenced by #chanext I cleaned it up and put it into a single extension method. Hope this can help someone.
Partial Class Uploader
Inherits Page
Private Sub UploadFile()
Dim sFileName As String
Dim oPdf As MigraDoc.Rendering.PdfDocumentRenderer
sFileName = "File Name With Spaces #22.pdf"
With Me.Request.Browser
If .Browser = "InternetExplorer" OrElse .Browser = "IE" Then
sFileName = sFileName.EncodeForIE
Else
sFileName = String.Format("""{0}""", sFileName)
End If
End With
oPdf = New MigraDoc.Rendering.PdfDocumentRenderer
oPdf.Document = FileFactory.CreatePdf()
oPdf.RenderDocument()
Using oStream As New MemoryStream
oPdf.Save(oStream, False)
Me.Response.Clear()
Me.Response.ContentType = "application/pdf"
Me.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", sFileName))
Me.Response.AddHeader("content-length", oStream.Length)
Me.Response.BinaryWrite(oStream.ToArray)
End Using
Me.Response.Flush()
Me.Response.End()
End Sub
End Class
Public Module StringExtensions
<Extension()>
Public Function EncodeForIE(Url As String) As String
Dim _
sReservedChars,
sEncodedString As String
sReservedChars = "$-_.+!*'(),#=&"
With New StringBuilder
Url.ToList.ForEach(Sub(C)
If Char.IsLetterOrDigit(C) OrElse sReservedChars.Contains(C) Then
.Append(C)
Else
With New StringBuilder
C.ToBytes.ToList.ForEach(Sub(B)
.AppendFormat("%{0}", Convert.ToString(B, 16))
End Sub)
sEncodedString = .ToString
End With
.Append(sEncodedString)
End If
End Sub)
Return .ToString
End With
End Function
<Extension()>
Public Function ToBytes(Chr As Char) As Byte()
Return Encoding.UTF8.GetBytes(Chr.ToString)
End Function
End Module

IE7 having problems when redirected to large excel files

We've got a page in our asp.net web system that uses response.redirect to redirect the user directly to an excel file so it will download "automatically" without the user having to to a right click / save as.
This works great - except for files over about 100k in IE7. Other browsers just download the large file fine, and IE works fine under that threshold, but at somewhere about 200k, IE just starts handing out "page cannot be displayed" errors.
Obviously, we'd like the user to be able to download in IE as well - any ideas? Is there some kind of download size threshold thing I can override?
You can make a simple ashx wrapper around this file and force IE to download this file by using http header: "Content-disposition: attachment; filename=fname.xls"
How To Raise a "File Download" Dialog Box for a Known MIME Type
I prefer a different method for sending files. It works for me with all kinds of different types and sizes of files.
Instead of using Response.Redirect, allow the link to the file to do a postback where you modify the response, like so:
Public Shared Sub SendFileToBrowser(ByRef response As HttpResponse, ByVal filepath As String, Optional ByVal filename As String = "", Optional ByVal contentType As String = "", Optional ByVal disposition As String = "", Optional ByVal contentLength As String = "")
Dim ext As String = filepath.Substring(filepath.Length - 3, 3)
If String.IsNullOrEmpty(contentType) Then
If ext = "pdf" Then
contentType = "application/pdf"
Else
contentType = "application/file"
End If
End If
If String.IsNullOrEmpty(disposition) Then
disposition = "attachment"
End If
If String.IsNullOrEmpty(filename) Then
''//Test for relative url path
Dim fileparts As String() = filepath.Split("/")
If fileparts.Length > 1 Then
filename = fileparts(fileparts.Length - 1)
Else
''//Test for absolute file path
Dim fileparts2 As String() = filepath.Split("\") ''//" SO: Fix syntax highlighting
If fileparts2.Length > 1 Then
filename = fileparts2(fileparts2.Length - 1)
Else
''//Just give it a temp name
filename = "temp." & ext
End If
End If
End If
response.Clear()
response.AddHeader("content-disposition", disposition & ";filename=" & filename)
If Not String.IsNullOrEmpty(contentLength) Then
response.AddHeader("Content-Length", contentLength)
End If
response.ContentType = contentType
response.Cache.SetCacheability(HttpCacheability.Public)
response.TransmitFile(filepath)
response.End()
End Sub
Note: Using "''//" for comments so that the syntax highlighter works properly. This still compiles properly as well.
This works for us in IE6 and IE7.

Resources