Itextsharp open new tab ISSUE - asp.net

I need to open pdf in the new tab, it works and file show perfect, but if I open File with notepadd++, after EOF there are some NULL char (see pics).
It happen only I open it in new tab and use memorystream, the string after EOF create some problem the parser of client, whats wrong?.
This is code:
Dim mswithPage As New MemoryStream()
Dim SessValue As String = Request.QueryString("s")
Dim NOrder As String = Request.QueryString("odv")
mswithPage = CType(Session(SessValue), MemoryStream)
Response.Clear()
Response.ContentType = "Application/pdf"
Response.AddHeader("content-disposition", "inline;filename=" & NOrder & ".pdf")
Response.OutputStream.Write(mswithPage.GetBuffer(), 0, mswithPage.GetBuffer().Length)
Response.OutputStream.Flush()
Response.OutputStream.Close()
Response.End()

The issue
An issue is in this line:
Response.OutputStream.Write(mswithPage.GetBuffer(), 0, mswithPage.GetBuffer().Length)
Even more precisely its final argument mswithPage.GetBuffer().Length - you should use the number of actually used bytes in the buffer but you use the size of the complete buffer.
A solution
Thus, use mswithPage.Length instead:
Response.OutputStream.Write(mswithPage.GetBuffer(), 0, mswithPage.Length)
... and if the MemoryStream already is closed
If the MemoryStream already is closed, the solution above doesn't work anymore because its Length property can only be used on open streams.
What does work on closed streams, though, is the ToArray method! Thus, you can instead use
Response.OutputStream.Write(mswithPage.ToArray())
(Actually it is funny that ToArray works on closed streams but Length does not. After all, ToArray essentially returns a copy of the first Length many bytes of the internal buffer...)

Related

Getting a corrupted XLSX file when writing it to Response.OutputStream

In ASP.Net, I'm using NPOI to write save to an Excel doc and I've just moved to version 2+. It worked fine writing to xls but switching to xlsx is a little more challenging. My new and improved code is adding lots of NUL characters to the output file.
The result is that Excel complains that there is "a problem with some content" and do I want them to try to recover?
Here is a pic of the xlsx file that was created from my Hex editor:
BadXlsxHexImage Those 00s go on for several pages. I literally deleted those in the editor until the file opened without an error.
Why does this code add so many NULs to this file??
using (var exportData = new MemoryStream())
{
workbook.Write(exportData);
byte[] buf = exportData.GetBuffer();
string saveAsFileName = sFileName + ".xlsx";
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}; size={1}", saveAsFileName, buf.Length.ToString()));
Response.Clear();
Response.OutputStream.Write(buf, 0, buf.Length);
exportData.Close();
Response.BufferOutput = true;
Response.Flush();
Response.Close();
}
(I've already tried BinaryWrite in place of OutputStream.Write, Response.End in place of Response.Close, and setting Content-Length with the length of the buffer. Also, none of this was an issue writing to xls.)
The reason you are getting a bunch of null bytes is because you are using GetBuffer on the MemoryStream. This will return the entire allocated internal buffer array, which will include unused bytes that are beyond the end of the data if the buffer is not completely full. If you want to get just the data in the buffer (which you definitely do), then you should use ToArray instead.
That being said, why are you writing to a MemoryStream at all? You already have a stream to write to: the OutputStream. Just write the workbook directly to that.
Try it like this:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", saveAsFileName));
workbook.Write(Response.OutputStream);
Response.Flush();
Response.Close();

Get blob from SQL and write to browser for download

ASP / .NET 3.5 & SQL Server 2005
I'm trying to download a blobbed PDF from our SQL database, then without physically writing the file anywhere, output the file and download to user with the "Save / Open".
The code processes through without throwing an Exception, but no download occurs.
To be honest I'm not certain how close this is to "working"... I've tried piecing together several different samples from various posts, being that nothing seems to match my particular situation.
Response.ClearContent()
Response.Clear()
Response.ContentType = "application/pdf"
Response.AddHeader("Content-Disposition", "attachment; filename=MY_DOWNLOAD.pdf")
Dim bufferSize As Integer = 100
Dim outByte(bufferSize - 1) As Byte
Dim strSql As String = "SELECT BlobData, BlobData FROM Attachment WHERE RecordID = " & CInt(Request.QueryString("pid").ToString)
Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("SqlServer").ConnectionString)
connection.Open()
Dim scSql As SqlCommand = New SqlCommand(strSql, connection)
Dim sdrSql As SqlDataReader = scSql.ExecuteReader(CommandBehavior.SequentialAccess)
Do While sdrSql.Read
Dim startIndex As Long = 0
Dim retVal As Long = sdrSql.GetBytes(1, startIndex, outByte, 0, bufferSize)
Do While retVal = bufferSize
Response.BinaryWrite(outByte)
Response.Flush()
startIndex += bufferSize
retVal = sdrSql.GetBytes(1, startIndex, outByte, 0, bufferSize)
Loop
Response.BinaryWrite(outByte)
Response.Flush()
Response.End()
Loop
sdrSql.Close()
End Using
I would strongly recommend saving the files to a temporary location on disk, then letting Response.TransmitFile send the file for you.
The problem with the approach that you are using is that you will have two copies of each file in memory. If your files are 100MB each and you have 100 simultaneous users, this will result in 20GB of memory being used by your app.
Also, your current code will send at most one file to the user since you end the response within the SQL loop.
Finally, Response.End is no longer recommended since it causes problems in non-IE browsers. Instead, use Context.ApplicationInstance.CompleteRequest().
As pointed out in the comments, you should wrap the creation of the temp file and TransmitFile operation in a try/finally statement and delete the temp file in the finally portion. This will handle various exceptions (such as the end user getting disconnected part way through the transmission process) and ensure that you don't have a bunch of temp files stranded on your disk.
While I agree with competent_tech's answer above, if you still feel like you don't want to write the file to disk and want to fetch it, then convert it to byte array and stream it as a "Save As", then you could try the following (sorry it's C#, but you can convert it to VB.NET pretty easily):
byte[] byteArray = GetBytesFromSource();
Response.AddHeader("Content-Disposition", "attachment; filename=Test.pdf");
Response.AddHeader("Content-Length", byteArray.Length.ToString(CultureInfo.CurrentCulture));
Response.ContentType = "application/octet-stream";
Response.OutputStream.Write(byteArray, 0, byteArray.Length);
Response.Flush();
I just tested this and it works like a charm :)

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.

Getting a dynamically created PDF from a URL

I have a need to aquire a pdf file generated from an aspx site.
Backstory:
I want to get schedueles from a website, I have succeded in getting the url to the scheduele, containing parameters. If you follow the url you will be shown a PDF stream, created by the site using given parameters.
http://www.novasoftware.se/ImgGen/schedulegenerator.aspx?format=pdf&schoolid=57240/sv-se&type=1&id=%7bD8920398-FA90-4960-BD47-69A8EFF7204D%7d&period=&week=38&mode=0&printer=1&colors=2&head=1&clock=1&foot=1&day=0&width=2480&height=3507&count=1&decrypt=0
This URL is what the site uses to get the appropriate scheduele and display it as a pdf.
Since it's not theoretically a PDF file, I can't download it as one using:
Dim Downloader As New WebClient
Downloader.DownloadFile(URL, fileName)
Neither can i download the content as a string using...
Dim Downloader As New WebClient
Dim Result As String = Downloader.DownloadString(URL)
...since it will result in an 500 Server Error due to missing parameters.
The only way of displaying the file/stream/document or whatever it's real name is, is to visit the given url through a browser. Given that, I tried to grab the PDF through a WebBrowser control. But since it "Can't display the XML page" (error displayed when navigating to the scheduele URL) I can't use that approach either.
So my question is, How do I download this data as a PDF or How do I get this data as a Stream that i can read with StreamReader?
Sidenotes:
The page uses no further client-side connections so I cannot backtrack it.
(I used Fiddler2 to track all the connections)
Using Fiddler, I can tell that the url SomethingSomething.com/Something.aspx generates a PDF and displays it. First few lines of the generated document (through Fiddler)
%PDF-1.4
%����
%
%wPDF by WPCubed GmbH V3.54x[0]
%
%
1 0 obj
<>
There are more information I can get from Fiddler about this site, so if you need it either try it yourself or ask me to add the information here.
Use the code below to download the file to memory stream:
Dim webRes As HttpWebResponse = Nothing
Dim memStream As New MemoryStream
Try
Dim webReq As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
webReq.Credentials = CredentialCache.DefaultCredentials
webRes = webReq.GetResponse
Dim resStream As Stream = webRes.GetResponseStream
Dim bytesRead As Integer
Do
Dim buffer(1023) As Byte
bytesRead = resStream.Read(buffer, 0, buffer.Length)
memStream.Write(buffer, 0, bytesRead)
Loop Until bytesRead = 0
Catch ex As Exception
Finally
If webRes IsNot Nothing Then
webRes.Close()
webRes = Nothing
End If
memStream.Seek(0, SeekOrigin.Begin)
End Try
' optionally save the stream into a file
memStream.WriteTo(New FileStream("d:\filename.pdf", FileMode.Create))

I have path Manipulation issue. The following code is placed in Page_load method of ASPx page + VB

If Request.QueryString("ID") = "" Then
folderDirectory = Global.FileUpload.GetFolderDirectory(Request.QueryString("TFID"))
If Not File.Exists(folderDirectory + fileName) Then
If Not Directory.Exists(folderDirectory) Then
Directory.CreateDirectory(folderDirectory)
End If
Dim bufferSize As Integer = Me.fileUpload.PostedFile.ContentLength
Dim buffer As Byte() = New Byte(bufferSize) {}
' write the byte to disk
Using fs As New FileStream(Path.Combine(folderDirectory, fileName), FileMode.Create)
Dim bytes As Integer = Me.fileUpload.PostedFile.InputStream.Read(buffer, 0, bufferSize)
' write the bytes to the file stream
fs.Write(buffer, 0, bytes)
End Using
Else
CallOnComplete("error", "", "Error uploading '" & fileName & "'. File has been exists!")
Exit Sub
End If
But Fortify scan report for the above sample code shows Path Manipulation issue as high. I Need help to modify above code so that it can pass fortify scan
It is showing me error at folderDirectory
Usually, when your code works inside a web application you don't have the liberty to use the full file system as you do on your local PC. Any kind of 'Path Manipulation' is suspicious.
You should try to recode your works using Server.MapPath method.
Pay particular attention to this warning
For security reasons, the AspEnableParentPaths property has a default value set to FALSE.
Scripts will not have access to the physical directory structure unless AspEnableParentPaths
is set to TRUE.

Resources