Failed to download files when deployed to Azure App Service - c#

Large file download code found running on IIS.
But it stops at Azure AppService.
The file will download well and then stop when it reaches 1 GB.
Is there a problem with Azure App Service settings?
Please let me know what the problem is.
This is the ashx file code.
public void ProcessRequest(HttpContext context)
{
Stream stream = null;
int bytesToRead = 10000;
byte[] buffer = new Byte[bytesToRead];
string Url = context.Request.QueryString["Url"];
string FileName = HttpUtility.UrlEncode(context.Request.QueryString["FileName"]).Replace("+","%20");
try
{
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(Url);
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)
{
length = stream.Read(buffer, 0, bytesToRead);
resp.OutputStream.Write(buffer, 0, length);
resp.Flush();
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();
}
}
}

To be honest, I didn't get any trouble using your code to download large files more than 1GB, even after publishing to Azure.
First, httpWebRequest doesn't not has any artificial size limit. I was wondering if you should consider other code to download, because it's not convenient if we couldn't see the details about the error log, and the download process.
Here is a issue might inspire you: C# - Is there a limit to the size of an httpWebRequest stream?
If you want try another code, try this:
static void Main(string[] args)
{
HttpWebRequestDownload hDownload = new HttpWebRequestDownload();
string downloadUrl = "http://speedtest.tele2.net/10MB.zip";
hDownload.DownloadProgressChanged += HDownloadOnDownloadProgressChanged;
hDownload.DownloadFileCompleted += delegate(object o, EventArgs args)
{
Debug.WriteLine("Download finished and saved to: "+hDownload.downloadedFilePath);
};
hDownload.Error += delegate(object o, string errMessage) { Debug.WriteLine("Error has occured !! => "+errMessage); };
hDownload.DownloadFile(downloadUrl);
}
private void HDownloadOnDownloadProgressChanged(object sender, HttpWebRequestDownload.ProgressEventArgs e)
{
Debug.WriteLine("progress: "+e.TransferredBytes+" => "+e.TransferredPercents);
}

Related

Unable to download the PDF file from URL

I need to download an .PDF file from a website : https://XXXXX/XXXX/XXXXXXX.pdf when user click's on link button. Below code is working fine in local but when I try to click on link button for downloading the file after deploying into server, First time it is working fire but next consecutive downloads, It is displaying as The XXXX.PDF download was interrupted or file cannot be downloaded.
try
{
string fullFileName =string.Empty;
LinkButton btn = (LinkButton)(sender);
string filepath = btn.CommandArgument;
string fileName = btn.Text;
if (fileName != null && !string.IsNullOrEmpty(fileName))
{
fullFileName = filePath +fileName ;
int bytesToRead = 10000;
// Buffer to read bytes in chunk size specified above
byte[] buffer = new Byte[bytesToRead];
//string fileName = System.IO.Path.GetFileName(fullFileName);
//Create a WebRequest to get the file
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | System.Net.SecurityProtocolType.Tls | (SecurityProtocolType)768/*TLS1.1*/ | (SecurityProtocolType)3072/*TLS1.2*/;
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(fullFileName);
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
var resp = HttpContext.Current.Response;
//Indicate the type of data being sent
resp.ContentType = "application/PDF";
//Name the file
resp.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
// Verify that the client is connected.
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);
// Flush the data
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
}
else
{
lblFile.Text = "File Name is missing";
lblFile.Visible = true;
}
}
catch (Exception ex)
{
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
Can someone please guide me why it is failing in server

Response.OutputStream.Write() Show data to browser Instead of Download

I use IHttpHandler to Download a file from Server.Everything works fine.
But it shows the data on browser instead of download it. I need to download the file from the server like we do download from other servers.
Could anyone suggest me, what should I do to download the file,
Or what is the convenient way to download a file(pdf,mp4 etc).
public void ProcessRequest(HttpContext context)
{
string strPathName = "";
if (context.Request.QueryString["fileName"] != null)
{
strPathName = context.Request.QueryString["fileName"].ToString();
}
string filename = context.Server.MapPath("~/MyPath/" + strPathName);
System.IO.Stream oStream = null;
oStream =
new System.IO.FileStream
(path: filename,
mode: System.IO.FileMode.Open,
share: System.IO.FileShare.Read,
access: System.IO.FileAccess.Read);
try
{
context.Response.ClearHeaders();
context.Response.Buffer = false;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Disposition", "attachment");
long lngFileLength = oStream.Length;
context.Response.AddHeader("Content-Length", lngFileLength.ToString());
long lngDataToRead = lngFileLength;
while (lngDataToRead > 0)
{
if (context.Response.IsClientConnected)
{
int intBufferSize = 8 * 1024;
byte[] bytBuffers =
new System.Byte[intBufferSize];
int intTheBytesThatReallyHasBeenReadFromTheStream =
oStream.Read(buffer: bytBuffers, offset: 0, count: intBufferSize);
context.Response.OutputStream.Write
(buffer: bytBuffers, offset: 0,
count: intTheBytesThatReallyHasBeenReadFromTheStream);
context.Response.Flush();
lngDataToRead =
lngDataToRead - intTheBytesThatReallyHasBeenReadFromTheStream;
}
else
{
lngDataToRead = -1;
}
}
}
catch { }
finally
{
if (oStream != null)
{
oStream.Close();
oStream.Dispose();
oStream = null;
}
context.Response.Close();
}
}
You can't directly download a file via ajax, it only returns the data into a JS variable in the page's code, instead of triggering a traditional request and download.
Your button needs to make a standard HTTP request, not an ajax call.

ASP.NET: Serve large video as content with one time url

I need serve a very large video (1gb) as content and in order to do it I using the following code.
protected void Page_Load(object sender, EventArgs e)
{
///check the token
///proceed if token if valid
Response.Clear();
Response.Buffer = false;
Response.ContentType = "video/mp4";
var wc = new WebClient();
string filePath = Server.MapPath("videos/vid.mp4");
//Context.Response.BinaryWrite(File.ReadAllBytes(filePath));
const int chunkSize = 1024; // read the file by chunks of 1KB
using (var file = File.OpenRead(filePath))
{
int bytesRead;
byte[] buffer = new byte[chunkSize];
while ((bytesRead = file.Read(buffer, 0, buffer.Length)) > 0)
{
Context.Response.BinaryWrite(buffer);
}
}
Response.End();
}
Questions
Is this the right way?
Video is getting played but video's seek bar is not working.
How to provide video in chunks to the client?

Opening large files

I have a processes I made that has been working well for several months now. The process recursively zips up all files and folders in a given directory and then uploads the zip file to an FTP server. Its been working, but now, the zip file is exceeding 2gb and its erroring out. Can someone please help me figure out how to get around this 2gb limit? I commented the offending line in the code. Here is the code:
class Program
{
// Location of upload directory
private const string SourceFolder = #"C:\MyDirectory";
// FTP server
private const string FtpSite = "10.0.0.1";
// FTP User Name
private const string FtpUserName = "myUserName";
// FTP Password
private const string FtpPassword = "myPassword";
static void Main(string[] args)
{
try
{
// Zip everything up using SharpZipLib
string tmpFile = Path.GetTempFileName();
var zip = new ZipOutputStream(File.Create(tmpFile));
zip.SetLevel(8);
ZipFolder(SourceFolder, SourceFolder, zip);
zip.Finish();
zip.Close();
// Upload the zip file
UploadFile(tmpFile);
// Delete the zip file
File.Delete(tmpFile);
}
catch (Exception ex)
{
throw ex;
}
}
private static void UploadFile(string fileName)
{
string remoteFileName = "/ImagesUpload_" + DateTime.Now.ToString("MMddyyyyHHmmss") + ".zip";
var request = (FtpWebRequest)WebRequest.Create("ftp://" + FtpSite + remoteFileName);
request.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.KeepAlive = false;
request.Timeout = -1;
request.UsePassive = true;
request.UseBinary = true;
// Error occurs in the next line!!!
byte[] b = File.ReadAllBytes(fileName);
using (Stream s = request.GetRequestStream())
{
s.Write(b, 0, b.Length);
}
using (var resp = (FtpWebResponse)request.GetResponse())
{
}
}
private static void ZipFolder(string rootFolder, string currentFolder, ZipOutputStream zStream)
{
string[] subFolders = Directory.GetDirectories(currentFolder);
foreach (string folder in subFolders)
ZipFolder(rootFolder, folder, zStream);
string relativePath = currentFolder.Substring(rootFolder.Length) + "/";
if (relativePath.Length > 1)
{
var dirEntry = new ZipEntry(relativePath) {DateTime = DateTime.Now};
}
foreach (string file in Directory.GetFiles(currentFolder))
{
AddFileToZip(zStream, relativePath, file);
}
}
private static void AddFileToZip(ZipOutputStream zStream, string relativePath, string file)
{
var buffer = new byte[4096];
var fi = new FileInfo(file);
string fileRelativePath = (relativePath.Length > 1 ? relativePath : string.Empty) + Path.GetFileName(file);
var entry = new ZipEntry(fileRelativePath) {DateTime = DateTime.Now, Size = fi.Length};
zStream.PutNextEntry(entry);
using (FileStream fs = File.OpenRead(file))
{
int sourceBytes;
do
{
sourceBytes = fs.Read(buffer, 0, buffer.Length);
zStream.Write(buffer, 0, sourceBytes);
} while (sourceBytes > 0);
}
}
}
You are trying to allocate an array possessing more than 2billion elements. .NET limits the maximum size of an array is System.Int32.MaxValue i.e. 2Gb is the upper bound.
You're better off reading the file in pieces an uploading it in pieces; e.g using a loop reading:
int buflen = 128 * 1024;
byte[] b = new byte[buflen];
FileStream source = new FileStream(fileName, FileMode.Open);
Stream dest = request.GetRequestStream();
while (true) {
int bytesRead = source.Read(buf, 0, buflen);
if (bytesRead == 0) break;
dest.Write(buf, 0, bytesRead);
}
The problem isn't in the zip, but in the File.ReadAllBytes call, which returns an array which has the default size limit of 2GB.
It is possible to disable this limit, as detailed here. I'm assuming you're already compiling this specifically for 64 bit to handle these kind of file sizes. Enabling this option switches .NET over to using 64 bit addresses for arrays instead of the default 32 bit addresses.
It would probably be better to split the archive into parts and upload them separately however. As far as I know the built in ZipFile class doesn't support multi-part archives, but several of the third party libraries do.
Edit: I was thinking about the resulting zip output, rather than the input. To load a huge amount of data INTO the ZipFile, you should use the Buffer based approach suggested by Petesh and philip.

How to upload photo to a server from .net winforms?

I have created a window form application in C#. There is a user registration section where user details are filled and a photo is uploaded. How to upload photo a common location in server not in client system. I need to upload the picture of user to a location in server so that the website section of the application can show the picture in the profile of user.
I would actually store the information including the picture in the database, so it's available from all your other applications.
if you simply want to copy a raw file from client computer to a centralized location, as a starting point:
private void button1_Click(object sender, EventArgs e)
{
WebClient myWebClient = new WebClient();
string fileName = textBox1.Text;
string _path = Application.StartupPath;
MessageBox.Show(_path);
_path = _path.Replace("Debug", "Images");
MessageBox.Show(_path);
myWebClient.UploadFile(_path,fileName);
}
private void btnBrowse_Click(object sender, EventArgs e)
{
OpenFileDialog ofDlg = new OpenFileDialog();
ofDlg.Filter = "JPG|*.jpg|GIF|*.gif|PNG|*.png|BMP|*.bmp";
if (DialogResult.OK == ofDlg.ShowDialog())
{
textBox1.Text = ofDlg.FileName;
button1.Enabled = true;
}
else
{
MessageBox.Show("Go ahead, select a file!");
}
}
Maybe best way is to use an FTP Server ,if you can install it .
Than you can upload file's using this code
FileInfo toUpload = new FileInfo("FileName");
System.Net.FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://serverip/FileName");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("UserName","Password");
Stream ftpStream = request.GetRequestStream();
FileStream file = File.OpenRead(files);
int length = 1024;
byte[] buffer = new byte[length];
int bytesRead = 0;
do
{
bytesRead = file.Read(buffer, 0, length);
ftpStream.Write(buffer, 0, bytesRead);
}
while (bytesRead != 0);
file.Close();
ftpStream.Close();
upload a file to FTP server using C# from our local hard disk.
private void UploadFileToFTP()
{
FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create("ftp://www.server.com/sample.txt");
ftpReq.UseBinary = true;
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
ftpReq.Credentials = new NetworkCredential("user", "pass");
byte[] b = File.ReadAllBytes(#"E:\sample.txt");
ftpReq.ContentLength = b.Length;
using (Stream s = ftpReq.GetRequestStream())
{
s.Write(b, 0, b.Length);
}
FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();
if (ftpResp != null)
{
if(ftpResp.StatusDescription.StartsWith("226"))
{
Console.WriteLine("File Uploaded.");
}
}
}

Categories