'http://www.domain.con/Image.jpg' is not a valid virtual path - asp.net

In subdomain.domainname, I have a generic handler which is supposed to load images from the domainname
Dim Path As String = "http://www.domainname/"
context.Response.ContentType = "image/jpg"
context.Response.WriteFile(Path & ImgName & ".jpg")
The problem is that i cannot add a physical path, since the Responce.WriteFile accepts a physical path. And i get that valid virtual path error.
So how can i load images when images exist in domainname and my generic handler is at subdomain.domainname?
Is there any trick, i could use?
I do not want to move the handler to the domainname

Well you could download the image first and then write the buffer to the response:
Using client = New WebClient()
' This assumes that http://www.domainname.com/ returns a JPEG image
Dim file As Byte() = client.DownloadData("http://www.domainname.com/")
context.Response.ContentType = "image/jpg"
Dim filename = Path.ChangeExtension(imgFile, "jpg")
context.Response.AppendHeader("Content-Disposition", "inline; filename=" & filename);
context.Response.OutputStream.Write(file, 0, file.Length)
End Using

Why not just redirect the request to the non-subdomain?
context.Response.Redirect(Path & ImgName & ".jpg")

I'm just throwing out the obvious here, but aren't you missing the top-level domain, i.e. .com?
http://www.mydomain.com/

Related

How to send multiple files with Response. ASP.NET

I'm trying to call below code in a loop hundreds of times:
Sub ExportReport(ByVal en As MyReport)
Dim warnings As Warning() = Nothing
Dim streamids As String() = Nothing
Dim mimeType As String = Nothing
Dim encoding As String = Nothing
Dim extension As String = Nothing
Dim bytes As Byte()
bytes = aReport.ServerReport.Render("WORD", Nothing, mimeType, encoding, extension, streamids, warnings)
Response.Buffer = True
Response.Clear()
Response.ContentType = mimeType
Response.AddHeader("content-disposition", "attachment; filename=" & en.ToString() & "." + extension)
Response.BinaryWrite(bytes)
Response.Flush()
Response.End()
End Sub
And I'm getting this error :
Server cannot append header after HTTP headers have been sent.
How can I change the code so that I can loop this piece of code? Thanks.
EDIT :
I added this line after Response.End()
Response.Redirect(Request.Url.AbsoluteUri)
And I get this error :
Cannot redirect after HTTP headers have been sent.
WWW works on a request / response mechanism. For every request there is only 1 response. You cannot change that basic mechanism. When browser sends a request it is expecting one and only one response. So if it receives more than 1 response, it either issues a warning to the user to block this behaviour or may choose to ignore the extra responses by itself. Thus these extra responses may be lost.
Having said that you have 2 options with you:
Zip all the files that you want to download and download as a single file.
You can use Popular framework Ionic.Zip.
First, keep all your files in a local directory on the server.
Then use this library to zip the entire folder.
Pseudo code:
Imports (var zip = New Ionic.Zip.ZipFile())
{
zip.AddDirectory("DirectoryOnDisk", "rootInZipFile")
Response.Clear()
Response.AddHeader("Content-Disposition", "attachment; filename=DownloadedFile.zip")
Response.ContentType = "application/zip"
zip.Save(Response.OutputStream)
Response.End()
}
Add a mechanism to issue multiple request using Javascript to get multiple responses, so browser still treats this behaviour as normal.
A normal web page will have a load of (headers) stuff set up for you already, but you don't want any of that: you want complete control over what is sent to the browser. If you cause a redirect to something which sends the headers shown in code later here, the browser will (normally) download the data.
In the code-behind you can have something like
Protected Sub btn_click(ByVal sender As Object, ByVal e As EventArgs) Handles btn.Click
Response.Redirect("~/sendfile.ashx?ref=" & enReference, False)
Context.ApplicationInstance.CompleteRequest()
End Sub
You will also need to add a generic handler (right-click on the project in Solution Explorer, Add->New Item... -> Visual Basic--Web--General choose "Generic Handler"; give it a name like sendfile.ashx) which is somewhat like
Imports System.IO
Public Class sendfile
Implements System.Web.IHttpHandler, IReadOnlySessionState
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim enReference = context.Request.QueryString("ref")
' do whatever is needed to get the report from enReference '
Dim bytes As Byte() = aReport.ServerReport.Render("WORD", Nothing, mimeType, encoding, extension, streamids, warnings)
Dim downloadName = yourfilename & "." & yourextension
context.Response.ContentType = "application/octet-stream"
context.Response.AddHeader("content-disposition", "attachment; filename=""" & downloadName & """" )
context.Response.BinaryWrite(bytes)
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
and you will need to work out the code to create the data to be sent.
If you don't need to use session state then you can remove the , IReadOnlySessionState part on the Implements line.
You might need to add context.Response.Flush(). If you find that the response does not have a Content-Length header, then you ought to add one so that the browser can show a meaningful download progress.

VB.NET FTP Picture Upload Error [duplicate]

This question already has answers here:
Zip file is getting corrupted after downloading from server in C#
(3 answers)
Closed 4 years ago.
I am trying to allow authenticated users to upload pictures to the server through FTP. The code works for the most part. The part that doesn't is that there is an issue in uploading the file. I have tried to upload a few different pictures and all of them are larger on the server and therefore, not properly constructed.
One picture I tried is 4.56MB on my computer and 8.24MB on the server. When I load the picture in Photo, it states "We can't open this file." The page location is at http://troop7bhac.com/pages/slideshowedit.aspx. The following is the VB.NET code behind the upload:
Sub uploadFile_Click(sender As Object, e As EventArgs)
lblUploadErrors.InnerHtml = ""
If (lstSlideshowChoose.SelectedValue = "") Then
lblUploadErrors.InnerHtml = "<p>A slideshow must be selected.</p>"
Else
If (FileUpload1.HasFile) Then
Dim nameList() As String
Dim successList() As String
Dim i As Integer = 0
For Each file As HttpPostedFile In FileUpload1.PostedFiles
Dim fileBytes() As Byte = Nothing
Dim fileName As String = Path.GetFileName(file.FileName)
Dim photoRE As New Regex("^[A-z0-9 _]{1,}\.jpg|JPG|jpeg|JPEG|png|PNG+$")
Dim photoSuccess As Boolean = photoRE.Match(fileName).Success
ReDim Preserve nameList(i)
ReDim Preserve successList(i)
If (photoSuccess = True) Then
Using fileStream As New StreamReader(file.InputStream)
fileBytes = Encoding.UTF8.GetBytes(fileStream.ReadToEnd())
fileStream.Close()
End Using
Try
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(ftpPath & lstSlideshowChoose.SelectedValue & "/" & fileName), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.UploadFile
request.Credentials = New NetworkCredential(ftpUser, ftpPass)
Using uploadStream As Stream = request.GetRequestStream()
uploadStream.Write(fileBytes, 0, fileBytes.Length)
uploadStream.Close()
End Using
Dim response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
response.Close()
successList(i) = "Success "
Catch ex As Exception
successList(i) = "Failed "
End Try
Else
successList(i) = "Failed "
End If
nameList(i) = fileName
i += 1
Next
For x As Integer = 0 To nameList.Count - 1
lblUploadErrors.InnerHtml += "<p>" & successList(x) & nameList(x) & "</p>"
Next
Else
lblUploadErrors.InnerHtml = "<p>You have not selected a picture to upload.</p>"
End If
End If
End Sub
The files are obtained through an ASP.NET FileUpload control. The control has been set to allow multiple files at once.
Any help to figure out why the pictures are not uploading properly would be greatly appreciated.
EDIT: I tried Martin Prikryl's possible duplicate solution. Had to change it from C# to VB.NET. It failed. I tried David Sdot's solution and it also failed. Both solutions returned the same errors.
If the page was ran on my local machine, it returned "C:\Program Files (x86)\IIS Express\PictureName.JPG." If the page was ran on the server, it returned "C:\Windows\SysWOW64\inetsrv\PictureName.JPG." Both errors are of the System.IO.FileNotFoundException class.
Your Problem is here:
Using fileStream As New StreamReader(file.InputStream)
fileBytes = Encoding.UTF8.GetBytes(fileStream.ReadToEnd())
fileStream.Close()
Using
Your image is read as text. From this text you get the bytes UTF8 byte values, thats why your image is nearly twice the size when uplaoded. You need the bytes from the image, without converting them to something else.
fileBytes = File.ReadAllBytes(file.FileName)

Asp.Net hide url of file

I hav an Asp.NET site that displays a PDF/Word/Excel file but I would like to hide the location of the file i.e. if the user requests a file via a link instead of displaying the path just open the filename, I've seen some other posts on other sites but since they are old they do not wok.
Any help is appreciated.
Thanks
Use ASP.NET ASHX Handler
Some ASP.NET files are dynamically generated. They are generated with C# code or disk resources. These files do not require web forms. Instead, an ASHX generic handler is ideal. It can dynamically return an image from a query string, write XML, or any other data.
One way to get around this is to write a custom .ashx handler, which implements IHttpHandler.
Implement the ProcessRequest(..) method, and pipe the file out in the response (here's an example from an application I wrote a while back:
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim inline As Boolean = Boolean.Parse(context.Request.QueryString("Inline"))
Dim fileName As String = context.Request.QueryString("fileName")
If (fileName.Contains("\")) Then Throw New Exception(String.Format("Invalid filename {0}. Looks like a path was attempted", fileName))
Dim filePath = ConfigurationManager.AppSettings("FileDirectory") + "\" + fileName
With context.Response
.Buffer = True
.Clear()
If inline Then
.AddHeader("content-disposition", "inline; ; filename=" & IO.Path.GetFileName(filePath))
Else
.AddHeader("content-disposition", "attachment; ; filename=" & IO.Path.GetFileName(filePath))
End If
.WriteFile(filePath)
If fileName.ToUpper.EndsWith(".PDF") Then
.ContentType = "application/pdf"
ElseIf fileName.EndsWith(".htm") Or fileName.EndsWith(".html") Then
.ContentType = "text/html"
ElseIf fileName.EndsWith(".tif") Then
.ContentType = "image/tiff"
ElseIf fileName.EndsWith(".jpeg") Or fileName.EndsWith(".jpg") Then
.ContentType = "image/jpeg"
End If
.End()
End With

Post file to ashx page on different server

I have a asp.net web site where the user chooses some files with a fileUpload Control. Then the files need to be posted to another server
My domain is [http://www.mydomain.com]
The address where i have to upload the files is something like: [https://www.externaldomain.com/upload.ashx?asd2t423eqwdq]
I have tried the following:
Dim uploadedFiles As HttpFileCollection = Request.Files
Dim userPostedFile As HttpPostedFile = uploadedFiles(0)
Dim filePath As String
filePath = "https://www.externaldomain.com/upload.ashx?asd2t423eqwdq" & "/" & userPostedFile.FileName
userPostedFile.SaveAs(filePath)
But i get an error:
The SaveAs method is configured to require a rooted path, and the path 'https://www.externaldomain.com/upload.ashx?asd2t423eqwdq/Core CSS 3.pdf' is not rooted
I searched the internet, but all i could find were examples on how to upload to the page's server.
EDIT:
I used HttpWebRequest to access the link and it partialy worked. I also need to send 2 POST parameters, username and password.
This is how my code looks like now:
Dim link As String = "https://www.externaldomain.com/upload.ashx?e9879cc77c764220ae80"
Dim req As HttpWebRequest = WebRequest.Create(link)
Dim boundary As String = "-----"
req.ContentType = "multipart/form-data; boundary=" + boundary
req.Method = "POST"
Dim username As String = "test"
Dim userpass As String = "123456"
Dim credentials() As Byte = Encoding.UTF8.GetBytes("username=" & username & "&password=" & userpass & "--\r\n" & boundary & "--\r\n")
Dim separators() As Byte = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n")
Dim uploadedFiles As HttpFileCollection = Request.Files //this is where i take the file that the user wants to upload
Dim userPostedFile As HttpPostedFile = uploadedFiles(0)
//i convert the file to a byte array
Dim binaryReader As IO.BinaryReader
Dim fileBytes() As Byte
binaryReader = New BinaryReader(userPostedFile.InputStream)
fileBytes = binaryReader.ReadBytes(userPostedFile.ContentLength)
//'get the request length
req.ContentLength += credentials.Length
req.ContentLength += userPostedFile.ContentLength
req.ContentLength += separators.Length
req.ContentLength += 1
Dim dataStream As Stream
dataStream = req.GetRequestStream
dataStream.Write(credentials, 0, credentials.Length)
dataStream.Write(separators, 0, separators.Length)
dataStream.Write(fileBytes, 0, fileBytes.Length)
dataStream.Close()
Dim response As HttpWebResponse = req.GetResponse
The error i get is "forbidden". The username and password are 100% correct. I think the problem is that i do not create the request correctly. If i post only the credentials i get the error saying that i have no file...
Any ideas?
Eventually I used the code provided here http://aspnetupload.com/
I compiled it into a dll and added a reference to my solution.
It works :)

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

Resources