FileStream Object taking forever to push file to browser - asp.net

I'm using a filestream object to push a report in excel format from our DB, and it works fine for reports that are reasonable in terms the number of rows, however there's one report that has over 15K rows and the site times out after 20 minutes - I know I could increase the timeout, but even 20 minutes is unaccaptable right now. Is there any way to speed things up? Here is my current code:
string path = Server.MapPath(#"~\");
string sourceName = Path.Combine(path, "Demo", "Report_Template", templateName);
string newFileName = Path.Combine(Global.demo_data_directory, #"Reports", #"Demo Download Activity Report.xlsx"); // Path.Combine(path, "Demo_Data", "Reports", Filename + ".xlsx");
string copyresults = Utilities.CopyFile(sourceName, newFileName);
if (copyresults != "Copied file")
{
DemoDAL.ErrorLog("GenerateDownloadActivityReportFile.Page_Load: Copy Error - " + copyresults);
}
else
{
document = SpreadsheetDocument.Open(newFileName, true);
wbPart = document.WorkbookPart;
DataTable datatbl = (DataTable)Session["gvPOC"];
CreateReport(datatbl);
// ADDED THIS *********************************************************************************************************
//wbPart.Workbook.Save();
using (FileStream fsSource = new FileStream(newFileName, FileMode.Open, FileAccess.Read, FileShare.Read, 10240))
{
// Read the source file into a byte array.
byte[] bytes = new byte[fsSource.Length];
int numBytesToRead = (int)fsSource.Length;
int numBytesRead = 0;
while (numBytesToRead > 0)
{
// Read may return anything from 0 to numBytesToRead.
int n = fsSource.Read(bytes, numBytesRead, numBytesToRead);
// Break when the end of the file is reached.
if (n == 0)
break;
numBytesRead += n;
numBytesToRead -= n;
}
numBytesToRead = bytes.Length;
StreamFileToBrowser(newFileName, bytes);
}
File.Delete(newFileName);
}
public void StreamFileToBrowser(string sfilename, byte[] fileBytes)
{
try
{
Response.Clear();
Response.ClearHeaders();
Response.AppendHeader("Content-disposition", String.Format("attachment; filename=\"{0}\"", System.IO.Path.GetFileName(sfilename)));
Response.AppendHeader("Content-Type", "binary/octet-stream");
Response.AppendHeader("Content-length", fileBytes.Length.ToString());
Response.BinaryWrite(fileBytes);
if (Response.IsClientConnected)
Response.Flush();
}
catch (Exception ex)
{
DemoDAL.ErrorLog("StreamFileToBrowser: " + ex.Message);
}
}

Related

Problems with downloading pdf file from web api service

I'm trying to set up a web api service that searches for a .pdf file in a directory and returns the file if it's found.
The controller
public class ProductsController : ApiController
{
[HttpPost]
public HttpResponseMessage Post([FromBody]string certificateId)
{
string fileName = certificateId + ".pdf";
var path = #"C:\Certificates\20487A" + fileName;
//check the directory for pdf matching the certid
if (File.Exists(path))
{
//if there is a match then return the file
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(path, FileMode.Open);
stream.Position = 0;
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = fileName };
result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
result.Content.Headers.ContentDisposition.FileName = fileName;
return result;
}
else
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.Gone);
return result;
}
}
}
I'm calling the service with the following code
private void GetCertQueryResponse(string url, string serial)
{
string encodedParameters = "certificateId=" + serial.Replace(" ", "");
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.AllowAutoRedirect = false;
byte[] bytedata = Encoding.UTF8.GetBytes(encodedParameters);
httpRequest.ContentLength = bytedata.Length;
Stream requestStream = httpRequest.GetRequestStream();
requestStream.Write(bytedata, 0, bytedata.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)httpRequest.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
byte[] bytes = null;
using (Stream stream = response.GetResponseStream())
using (MemoryStream ms = new MemoryStream())
{
int count = 0;
do
{
byte[] buf = new byte[1024];
count = stream.Read(buf, 0, 1024);
ms.Write(buf, 0, count);
} while (stream.CanRead && count > 0);
ms.Position = 0;
bytes = ms.ToArray();
}
var filename = serial + ".pdf";
Response.ContentType = "application/pdf";
Response.Headers.Add("Content-Disposition", "attachment; filename=\"" + filename + "\"");
Response.BinaryWrite(bytes);
}
}
This appears to be working in the sense that the download file dialogue is shown with the correct file name and size etc, but the download takes only a couple of seconds (when the file sizes are >30mb) and the files are corrupt when I try to open them.
Any ideas what I'm doing wrong?
Your code looks similar to what Ive used in the past, but below is what I typically use:
Response.AddHeader("content-length", myfile.Length.ToString())
Response.AddHeader("content-disposition", "inline; filename=MyFilename")
Response.AddHeader("Expires", "0")
Response.AddHeader("Pragma", "Cache")
Response.AddHeader("Cache-Control", "private")
Response.ContentType = "application/pdf"
Response.BinaryWrite(finalForm)
I post this for 2 reasons. One, add the content-length header, you may have to indicate how large the file is so the application waits for the whole response.
If that doesn't fix it. Set a breakpoint, does the byte array content the appropriate length (aka, 30 million bytes for a 30 MB file)? Have you used fiddler to see how much content is coming back over the HTTP call?

How to Play decrypted file

For video's to be copy protected , I thought of
Step-1) encrypting video files with key.
step-2)Decrypting a file OR decrypt in memory stream.
Step-3) Play decrypted file OR Play from Memory stream.
I have succesfully encrypted and decrypted a video file with key. But don't know how to play decrypted file(.dnc file).
Can somebody will please help me to play video file from decrypted (File or Memory Stream).
Code for Decryption
private void Decryption(string filePath)
{
try
{
DateTime current = DateTime.Now;
string encName = filePath + "data" + ".enc";
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
#region Seperate key and data
byte[] alldata = File.ReadAllBytes(filePath);
byte[] getencryptedkey = new byte[128];
byte[] data = new byte[alldata.Length - 128];
for (int i = 0; i < alldata.Length - 128; i++)
{ data[i] = alldata[i]; }
for (int i = alldata.Length - 128, j = 0; i < alldata.Length; i++, j++)
{ getencryptedkey[j] = alldata[i]; }
using (BinaryWriter bw = new BinaryWriter(File.Create(encName)))
{
bw.Write(data);
bw.Close();
}
#endregion
#region key decryption
StreamReader reader = new StreamReader("PublicPrivateKey.xml");
string publicprivatekeyxml = reader.ReadToEnd();
RSA.FromXmlString(publicprivatekeyxml);
reader.Close();
byte[] decryptedKey = RSA.Decrypt(getencryptedkey, false);
pwd = System.Text.ASCIIEncoding.Unicode.GetString(decryptedKey);
byte[] dk = null;
byte[] div = null;
crm.getKeysFromPassword(pwd, out dk, out div);
cryptoKey = dk;
cryptoIV = div;
#endregion
string ext = Path.GetExtension(encName).ToLower();
if (ext != ".enc")
{
MessageBox.Show("Please Enter correct File");
return;
}
string dncName = Path.GetDirectoryName(encName) + "\\" + Path.GetFileNameWithoutExtension(encName);
dncName = current.Date.Day.ToString() + current.Date.Month.ToString() + current.Date.Year.ToString() + current.TimeOfDay.Duration().Hours.ToString() + current.TimeOfDay.Duration().Minutes.ToString() + current.TimeOfDay.Duration().Seconds.ToString() + ".wmv";
try
{
if (crm.DecryptData(encName, dncName, cryptoKey, cryptoIV))
{
FileInfo fi = new FileInfo(encName);
FileInfo fi2 = new FileInfo(dncName);
if ((fi.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{ fi.Attributes &= ~FileAttributes.ReadOnly; }
//copy creation and modification time
fi2.CreationTime = fi.CreationTime;
fi2.LastWriteTime = fi.LastWriteTime;
//delete encrypted file
File.Delete(encName);
MessageBox.Show("File Decrypted");
}
else
{
MessageBox.Show("The file can't be decrypted - probably wrong password");
}
}
catch (CryptographicException ex)
{ MessageBox.Show(ex.Message); }
catch (IOException ex)
{ MessageBox.Show(ex.Message); }
catch (UnauthorizedAccessException ex)
{ //i.e. readonly
MessageBox.Show(ex.Message);
}
}
catch (Exception ex)
{ MessageBox.Show(ex.Message); }
}
To copy-protect a video file, the best way to accomplish it used to be apply DRM to it. That way you can restrict how may times it should play or how long it should be available to the user, but that still could be broken via a lot of means.
You cannot make any video 100% copy protected. Please read the article below. If that was the case, the hollywood movies wouldnt be freely available via the torrent networks.
http://www.streamingmedia.com/Articles/Editorial/Featured-Articles/DRM-Is-Dead-79353.aspx

How to download excel file to a specific folder in asp.net

I need to download the excel to the specific folder
Example : D:\email
Now i was able to download the excel file in downloads ....but i need to download in D:\email
this is my code to create excel file :
protected void UploadDataTableToExcel(DataTable dtRecords)
{
string XlsPath = Server.MapPath(#"~/Add_data/test.xls");
string attachment = string.Empty;
if (XlsPath.IndexOf("\\") != -1)
{
string[] strFileName = XlsPath.Split(new char[] { '\\' });
attachment = "attachment; filename=" + strFileName[strFileName.Length - 1];
}
else
attachment = "attachment; filename=" + XlsPath;
try
{
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/vnd.ms-excel";
string tab = string.Empty;
foreach (DataColumn datacol in dtRecords.Columns)
{
Response.Write(tab + datacol.ColumnName);
tab = "\t";
}
Response.Write("\n");
foreach (DataRow dr in dtRecords.Rows)
{
tab = "";
for (int j = 0; j < dtRecords.Columns.Count; j++)
{
Response.Write(tab + Convert.ToString(dr[j]));
tab = "\t";
}
Response.Write("\n");
}
Response.End();
}
catch (Exception ex)
{
//Response.Write(ex.Message);
}
}
you can manually move the file after download using
string sourceFile = #"C:\Users\test\Documents\Downloads\test.xls";
string destinationFile = #"D:\emails\test.xls";
// To move a file or folder to a new location:
System.IO.File.Move(sourceFile, destinationFile);

Server.map path not working in asp.net

I am using this code to download a excel file which exist in my solution. I have added a folder FileUpload and added a excel file UploadCWF.xlsx. My code is workin in local host. But not working when I host this to server.I am getting error - Could not find a part of the path. My code -
string filePath = HttpContext.Current.Server.MapPath("~/FileUpload/");
string _DownloadableProductFileName = "UploadCWF.xlsx";
System.IO.FileInfo FileName = new System.IO.FileInfo(filePath + "\\" + _DownloadableProductFileName);
FileStream myFile = new FileStream(filePath + "\\" + _DownloadableProductFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
//Reads file as binary values
BinaryReader _BinaryReader = new BinaryReader(myFile);
//Check whether file exists in specified location
if (FileName.Exists)
{
try
{
long startBytes = 0;
string lastUpdateTiemStamp = File.GetLastWriteTimeUtc(filePath).ToString("r");
string _EncodedData = HttpUtility.UrlEncode(_DownloadableProductFileName, Encoding.UTF8) + lastUpdateTiemStamp;
Response.Clear();
Response.Buffer = false;
Response.AddHeader("Accept-Ranges", "bytes");
Response.AppendHeader("ETag", "\"" + _EncodedData + "\"");
Response.AppendHeader("Last-Modified", lastUpdateTiemStamp);
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment;filename=" + FileName.Name);
Response.AddHeader("Content-Length", (FileName.Length - startBytes).ToString());
Response.AddHeader("Connection", "Keep-Alive");
Response.ContentEncoding = Encoding.UTF8;
//Send data
_BinaryReader.BaseStream.Seek(startBytes, SeekOrigin.Begin);
//Dividing the data in 1024 bytes package
int maxCount = (int)Math.Ceiling((FileName.Length - startBytes + 0.0) / 1024);
//Download in block of 1024 bytes
int i;
for (i = 0; i < maxCount && Response.IsClientConnected; i++)
{
Response.BinaryWrite(_BinaryReader.ReadBytes(1024));
Response.Flush();
}
}
catch (Exception es)
{
throw es;
}
finally
{
Response.End();
_BinaryReader.Close();
myFile.Close();
}
}
else
System.Web.UI.ScriptManager.RegisterStartupScript(this, GetType(),
"FileNotFoundWarning", "alert('File is not available now!')", true);
Please some one help me.
You should first concat filepath and filename then get path using server.mappath.
You should write code like this
string filePath = HttpContext.Current.Server.MapPath("~/FileUpload/UploadCWF.xlsx");
System.IO.FileInfo FileName = new System.IO.FileInfo(filePath);

Downloading file on client side using absolute path .NET

string FilePath = HttpUtility.UrlDecode(Request.QueryString.ToString());
string[] s = FilePath.Split(new char[] { ',' });
string path = s[0];
string FileName = s[1];
String str = HttpContext.Current.Request.Url.AbsolutePath;
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
// response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName+ ";");
response.TransmitFile(path+FileName);
response.Flush();
response.End();
Above is the code in which i get location of audio file from another page . the audio file is located on a remote machine which is accesible using url e.g. http:\servername\audiofiles\filename.wav . response.Transmit and .WriteFile requires virtual path whereas response.Write() does not download file . How can i give the absolute url instead of virtual path to download file
Found the answer my self from another place :
string FilePath = HttpUtility.UrlDecode(Request.QueryString.ToString());
string[] s = FilePath.Split(new char[] { ',' });
string path = s[0];
string FileName = s[1];
int bytesToRead = 10000;
byte[] buffer = new Byte[bytesToRead];
try
{
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(path+FileName);
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
stream = fileResp.GetResponseStream();
var resp = HttpContext.Current.Response;
resp.ContentType = "application/octet-stream";
resp.AddHeader("Content-Disposition", "attachment; filename=\"" + FileName + "\"");
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
if (resp.IsClientConnected)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.OutputStream.Write(buffer, 0, length);
resp.Flush();
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
}

Resources