System.ArgumentOutOfRangeException in Response.BinaryWrite() - asp.net

I'm developing a asp.net webforms website using vb.net. In that list of files displayed in a gridview as links, when clicked on a link it calls OpenFile method. This code I found on the web is used to download file stored in webserver to client, this works fine for images but when I try to download .docx or .xlsx file it gives an error
in the line "Response.BinaryWrite(btFile)", but downloads the file. Given below is shortend version of the actual code
Page Code:
Protected Sub grvItemAttachments_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles grvItemAttachments.RowCommand
Try
If e.CommandName = "Open" Then
FileOpener.OpenFile(fileNameWithPath)
End If
Catch ex As Exception
ErrHandler.WriteError(ex.Message)
End Try
End Sub
File Opener Code:
Public Shared Sub OpenFile(fileNameWithPath as string)
Dim file As New FileInfo(fileNameWithPath)
Dim fs As System.IO.FileStream = Nothing
fs = System.IO.File.Open(fileNameWithPath, System.IO.FileMode.Open)
Dim btFile As Byte() = New Byte(fs.Length - 1) {}
fs.Read(btFile, 0, Convert.ToInt32(fs.Length))
fs.Close()
Response.AddHeader("Content-disposition", "attachment; filename=" & FileName)
Response.ContentType = GetFileType(file.Extension.ToLower())
Response.BinaryWrite(btFile)
Response.End()
End Sub
Error Message:
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values." & vbCrLf & "Parameter name: offset" & vbCrLf & " at System.Web.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count)" & vbCrLf & " at System.Web.HttpResponse.BinaryWrite(Byte[] buffer)" & vbCrLf & " at FileOpener.OpenFile(String FileName, String FolderName) in D:\Projects\VSS Projects\PIL WebSite\App_Code\Common\FileOpener.vb:line 25" & vbCrLf & " at Web_RTOView.grvItemAttachments_RowCommand(Object sender, GridViewCommandEventArgs e) in D:\Projects\VSS Projects\PIL WebSite\Web\RTOView.aspx.vb:line 310}
------
grvItemAttachments_RowCommand
Error Message: Specified argument was out of the range of valid values.
Parameter name: offset
Any idea how to solve this issue?

Why are you initializing your byte array to Length-1? Shouldn't it be exact size as Length?
In fact, you try to read the contents of the file from 0 to Length but your byte array length is Length-1

Related

ASP.Net Uploader - improve compression and downsizing

I use Classic ASP, not ASP.Net but I do have an ASP.net uploader that does a pretty good job. With some large files it compresses the image and makes it a good workable size. But there are times where the image actual is larger than the original.
I would really appreciate it if one of your experts can tweak my code and make it more efficient. Not knowing Net, I am at a loss.
Any help would be greatly appreciated.
Thank you.
Protected Sub btnUpload_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim strFileName As String = String.Format("Photo{0}.jpg", hdnAgentID.value)
If fupPhoto.HasFile Then
Try
If fupPhoto.PostedFile.ContentLength <= 10000000 Then
fupPhoto.SaveAs("M:\my path\" & strFileName)
resizeImage("M:\my path & strFileName)
End If
Catch ex As Exception
lblAlert.Text = "ERROR: " & ex.ToString()
End Try
hdnPhotoURL.Value = String.Format(https://websiteaddress/uploads/{0}, strFileName)
End If
strFileName = String.Format("Logo{0}.jpg", hdnAgentID.Value)
If fupLogo.HasFile Then
Try
If fupLogo.PostedFile.ContentLength <= 10000000 Then
fupLogo.SaveAs("M:\my path\" & strFileName)
resizeImage("M:\my path\" & strFileName)
End If
Catch ex As Exception
lblAlert.Text = "ERROR: " & ex.ToString()
End Try
hdnLogoURL.Value = String.Format(https://websiteaddress/uploads/{0}, strFileName)
End If
'Update UI and Create JS to populate the fields on memberpage.asp
pnlMain.Visible = true
litJS.visible = true
End Sub
Private Sub resizeImage(ByVal location As String)
' Get the source bitmap.
Dim bm_source As Bitmap = system.drawing.image.fromfile(location)
If bm_source.Width > 450 Then
Dim PercentageScaleWidth As Decimal = 450 / bm_source.Width
' Make a bitmap for the result.
Dim bm_dest As New Bitmap( _
CInt(bm_source.Width * PercentageScaleWidth), _
CInt(bm_source.Height * PercentageScaleWidth))
' Make a Graphics object for the result Bitmap.
Dim gr_dest As Graphics = Graphics.FromImage(bm_dest)
' Copy the source image into the destination bitmap.
gr_dest.DrawImage(bm_source, 0, 0, _
bm_dest.Width + 1, _
bm_dest.Height + 1)
' Save the result.
bm_source.Dispose()
bm_source = Nothing
Threading.Thread.Sleep(1000)
bm_dest.Save(location)
bm_dest.Dispose()
bm_dest = Nothing
gr_dest.Dispose()
gr_dest = Nothing
else
bm_source.Dispose()
bm_source = Nothing
End If
End Sub
I have had some jpg's resized from 375 kb to 660 kb. Seems odd that it would be larger which is why I was hoping that altering the code would cure that. Thanks for responding.

The Process cannot access the file because it is being created by another process in vb.net

I am using FilesystemWatcher to look for newfile in the directory.
The file type of investigation is .blf. It is being created of size almost 10MB (not constant but around/almost figure)
Once the file is created and being written completely, i want to copy the file into someother folder.
But the program immediately starts to copy even when the file is in process of being written and i get the error of
"The Process cannot access the file because it is being created by another process"
i want to make a condition to check if the file is completly created and then do the copy;
Below is my code:
Private Sub Fsw1_Created(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles Fsw1.Created
ListBox2.Items.Add("File- " & e.FullPath.ToString & " created at: " & System.DateTime.Now)
Dim blffolder As String = String.Format("C:\Users\nha4abt\Desktop\Main\blf_files" + "\{0}", DateTime.Today.ToString("dd-MMM-yyyy"))
'Check if subfolders exists or not
If (Not System.IO.Directory.Exists(blffolder)) Then
System.IO.Directory.CreateDirectory(blffolder)
End If
'Repeat steps 1-6
Dim destPath As String = Path.Combine(blffolder, Path.GetFileName(e.FullPath))
'System.Threading.Thread.Sleep(1000)
File.Copy(e.FullPath, destPath, True) 'copy all the files in destination folder
' Compare the two files that are referenced in the textbox controls.
If (FileCompare(e.FullPath, destPath)) Then
ListBox1.Items.Add(e.FullPath & "- is correctly copied :) ") ' put all the names in listbox; Not necessary
'To Add: make a log file .txt to put the record of all the files that are copied during the process
Dim strFile As String = String.Format(DestinationDirectory + "\Log_{0}.txt", DateTime.Today.ToString("dd-MMM-yyyy")) 'create a .txt file for log
Dim texttoappend As String
Dim timedate As String
timedate = DateTime.Now
texttoappend = e.FullPath + vbCrLf + "copied to" & vbCrLf & destPath & vbCrLf & "at" & timedate + vbNewLine & vbCrLf
File.AppendAllText(strFile, String.Format(texttoappend, Environment.NewLine))
Else
MessageBox.Show("Files are not equal.")
File.Copy(e.FullPath, destPath, True) 'copy again
End If
End Sub
I tried to use System.Threading.Thread.Sleep(1000) but couldn't run the program. please guide
I would suggest implementing a Function which checks if the file is still being used by another process and avoid System.Threading.Thread.Sleep(1000).
Original function here
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}

How to print a server side text file on a client printer programically

I have a server side application which creates a series of text files on the server. I need to allow a user to print one or more of the files directly on the client printer by clicking a button on a web page. That should bring up a printer selection window and then commence printing the selected web pages. I can handle the file selection and the printer selection windows but have not been able to get the files to print. I located code on Code Project (http://www.codeproject.com/Tips/689325/Send-PDF-files-directly-to-client-printer-without) which was described as doing exactly what I need but for for PDF files. I have attempted to adapt it to text files and the code runs without visible error, but nothing arrives at the printer and I do not know how to locate what happens after the code executes the value attribute of the Object tag of the web pages source code (see below). I program in VB.Net.
Here is the object tag in the source code:
<object id = "Object1" name="Txt1"
type="file/txt" width="1" height="1" >
<param name='SRC' value='<%= SReportFileName %>'/>
</object>
Here is the code from the code behind file:
Partial Class ViewResults_PrintingReports
Inherits System.Web.UI.Page
Public SReportFileName As String = ""
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim PathName As String = ""
Dim Uname As String = ""
Dim Iyr As String = ""
Dim Iwld As String = ""
Dim Iqtr As String = ""
Dim FName As String = ""
Dim CNumber As String = ""
Uname = "UserName"
Iyr = "3"
Iqtr = "1"
FName = "ReportA"
CNumber = "1"
Iwld = "1"
' Dim cs As ClientScriptManager = Page.ClientScript
PathName = "~/Competitions/" & Uname & "/BP/" & "World" & Iwld & "/Reports/QtrRpts" & Iwld & "." & Iyr & Iqtr & "/" & FName & "." & Iwld & CNumber & ".txt"
SReportFileName = PathName '// temp/mypdf.pdf
Try
ClientScript.RegisterStartupScript(GetType(Page), "MessagePopUp", "<script language=text/javascript>document.Txt1.printAll()</script>")
Catch ex As Exception
MsgBox("Problem printing file", , ex.Message)
End Try
End Sub
End Class
Any help would be appreciated.
You need to call javascript.
Here is the javascript
function PrintFile(FilePath) {
var printWin = window.open(FilePath, '','left=0,top=0,width=700,height=700,status=0');
printWin.focus();
printWin.print();
}
This is the codebehind of the button
Dim FilePath As String
FilePath = "This is your File Path"
Dim PrintFile As String
PrintFile = "PrintFile('" & FilePath & "')"
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "ntmtch", PrintFile, True)

VB.NET get bytes from SQL Table

It's been a while since I've been here. I've been working on an ASP project where the attachment is stored to DB. I'm trying to get the bytes stored in the table to a file.
I was able to make the file, however, I couldn't get the bytes from the table.
This is the code that enters the file to the table:
'Saves the upload file data to database for the using Request_ID after the request has been created
strFileName = FileUploadReqDtl.FileName
strFileExt = strFileName.Substring(strFileName.IndexOf(".") + 1)
intFileSize = FileUploadReqDtl.PostedFile.ContentLength()
Dim theDataSize As Byte() = New Byte(FileUploadReqDtl.PostedFile.ContentLength - 1) {}
Dim uploadedFile As HttpPostedFile = FileUploadReqDtl.PostedFile
Dim theData = uploadedFile.InputStream.Read(theDataSize, 0, CInt(FileUploadReqDtl.PostedFile.ContentLength))
I was able to create a link on a page that goes to another ASP page and tries to make the file downloadable. I know that the SQL is working properly to get the records from the table, however, I'm not able to get the bytes properly:
If (dr.HasRows = True) Then
While dr.Read()
' Casting the value returned by the datareader to the byte[] data type.
result = CType(dr.GetValue(0), Byte())
strFileName = dr.GetString(1)
Debug.Write("strFileName: " & strFileName & vbCrLf)
End While
End If
dr.Close()
cnToDb.Close()
ShowFile(strFileName, result, MimeType)
Catch ex As Exception
MsgBox("Uh oh, I couldn't get the attachment!")
Debug.Write("Uh oh, I couldn't get the attachment!")
Debug.Write(ex.Message & " - " & ex.StackTrace & vbCrLf & vbCrLf)
result = Nothing
End Try
This is the ShowFile function which finally "creates the file" with the bytes from the database:
Dim fileData() As Byte
fileData = byteFileData
Response.Clear()
Response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName)
Response.ContentType = MimeType
Response.BinaryWrite(fileData)
Response.End()
Response.Flush()
The exception I'm hitting that I'm having issues with is:
SQL: SELECT Data, FileName FROM tblFileUploadData WHERE Report_ID =
116
strFileName: TheAwesomeAttachment.txt A first chance exception of type
'System.Threading.ThreadAbortException' occurred in mscorlib.dll Uh
oh, I couldn't get the attachment!Thread was being aborted. - at
System.Threading.Thread.AbortInternal() at
System.Threading.Thread.Abort(Object stateInfo) at
System.Web.HttpResponse.End() at
WebApplication3.WebForm2.ShowFile(String strFileName, Byte[]
byteFileData, String MimeType) in C:\Users\Mike\documents\visual
studio
2010\Projects\WebApplication3\WebApplication3\Attachment.aspx.vb:line
81 at WebApplication3.WebForm2.getAttachment(Int32 RequestID,
String MimeType) in C:\Users\Mike\documents\visual studio
2010\Projects\WebApplication3\WebApplication3\Attachment.aspx.vb:line
56
A first chance exception of type
'System.Threading.ThreadAbortException' occurred in
WebApplication3.DLL An exception of type
'System.Threading.ThreadAbortException' occurred in
WebApplication3.DLL but was not handled in user code The thread '<No
Name>' (0x728) has exited with code 0 (0x0). The program '[13512]
WebDev.WebServer40.EXE: Managed (v4.0.30319)' has exited with code 0
(0x0). The program '[13512] WebDev.WebServer40.EXE: Program Trace' has
exited with code 0 (0x0).
Take a look at:
http://support.microsoft.com/kb/312629
"For Response.End, call the HttpContext.Current.ApplicationInstance.CompleteRequest method instead of Response.End to bypass the code execution to the Application_EndRequest event"
I like to create an .ashx file for this type of situation. You can link to it and it will download the file without showing a page.
Public Class DownloadFile
Implements System.Web.IHttpHandler
Public Sub ProcessRequest(context As HttpContext) Implements IHttpHandler.ProcessRequest
Try
Dim id As String = context.Request.QueryString("id")
Dim filename As String = ""
Dim output As Byte()
filename = ServiceHelper.GetFilenameByID(id)
output = ServiceHelper.GetFileBytesByID(id)
Dim ext As String = System.IO.Path.GetExtension(filename)
Dim contenttype As String
'clear the current output content from the buffer
context.Response.Clear()
'add the header that specifies the default filename for the
'Download/SaveAs dialog
context.Response.AddHeader("Content-Disposition", "attachment; filename=" & filename)
'add the header that specifies the file size, so that the browser
'can show the download progress
context.Response.AddHeader("Content-Length", output.Length.ToString())
'specify that the response is a stream that cannot be read by the
'client and must be downloaded
'Response.ContentType = "application/octet-stream"
context.Response.Buffer = True
Select Case ext
Case ".doc"
contenttype = "msword"
Case ".pdf"
contenttype = "pdf"
Case ".xls"
contenttype = "x-excel"
Case ".ppt"
contenttype = "ms-powerpoint"
Case Else
contenttype = "octet-stream"
End Select
context.Response.ContentType = "application/" & contenttype
context.Response.BinaryWrite(output)
'http://support.microsoft.com/kb/312629
'context.Response.End()
context.ApplicationInstance.CompleteRequest()
Catch
End Try
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class

ASP.NET/VB.NET FileUpload Control

I have a problem with FileUpload, when I select a file from the local machine, it will not bring the real path of the file, it will use the path for the project files and assume the file I am selecting is there, any ideas?
Example:
File name is "Q.JPG" and is in "C:\"
when I browse to "C:\" and select "Q.JPG" and click open, I get the following Error
Could not find file 'C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\q.jpg'.
So when I fire up the code for Uploading the file to FTP for example, it will return an error because file doesn't exist
HTML side:
<asp:FileUpload ID="FU" runat="server" Height="24px" />
Below is the VB code:
Protected Sub btnUpload_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpload.Click
If FU.PostedFile IsNot Nothing AndAlso FU.PostedFile.FileName <> "" Then
Dim MaxSize As Integer = FU.PostedFile.ContentLength
If MaxSize > "2097152" Then
lblUpload.Text = "The file size cannot exceed 2 MB"
btnSave.Focus()
GoTo 99
End If
'--------------------------
' set up request...
Dim LocFile As String = FU.PostedFile.FileName
Dim clsRequest As System.Net.FtpWebRequest = DirectCast(System.Net.WebRequest.Create("ftp://myftp.com/" & LocFile), System.Net.FtpWebRequest)
clsRequest.Credentials = New System.Net.NetworkCredential("username", "password")
clsRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
' read in file...
Dim bFile() As Byte = System.IO.File.ReadAllBytes(FU.PostedFile.FileName)
' upload file...
Dim clsStream As System.IO.Stream = clsRequest.GetRequestStream()
clsStream.Write(bFile, 0, bFile.Length)
clsStream.Close()
clsStream.Dispose()
'--------------------------
lblUpload.Text = "Uploaded"
btnSave.Focus()
Else
lblUpload.Text = "Choose a file to upload"
btnSave.Focus()
End If
99: 'Do Nothing
End Sub
The problem is you're trying to read in the PostedFile as a local file (on the web server), not from the HttpPostedFile object attached to the FileUploader.
Try:
Dim objFileStream As System.IO.Stream = FU.PostedFile.InputStream
Dim bFile(objFileStream.Length) As Byte
objFileStream.Read(bFile, 0, objFileStream.Length)
I tried something, and it worked..
FU.SaveAs("C:\" & FU.FileName)
'--------------------------
' set up request...
Dim LocFile As String = FU.PostedFile.FileName
Dim clsRequest As System.Net.FtpWebRequest = DirectCast(System.Net.WebRequest.Create("MyFTP.com" & LocFile), System.Net.FtpWebRequest)
clsRequest.Credentials = New System.Net.NetworkCredential("username", "password")
clsRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
It worked.. simply saved the file from FU (FileUpload) to C:\ and then setting the address to always start at C:\

Resources