I have been working on this application that enables user to log in into another website, and then download specified file from that server. So far I have succeeded in logging on the website and download the file. But everything ruins when it comes to zip files.
Is there any chunk of code that could be helpful in reading the .zip files byte by byte or by using stream reader?
I m using downloadfile() but its not returning the correct zip file.
I need a method by which I can read zip files. Can I do it by using ByteReader()
The code used to download zip file is
string filename = "13572_BranchInformationReport_2012-05-22.zip";
string filepath = "C:\\Documents and Settings\\user\\Desktop\\" + filename.ToString();
WebClient client = new WebClient();
string user = "abcd", pass = "password";
client.Credentials = new NetworkCredential(user, pass);
client.Encoding = System.Text.Encoding.UTF8;
try
{
client.DownloadFile("https://web.site/archive/13572_BranchInformationReport_2012-05-22.zip", filepath);
Response.Write("Success");
}
catch (Exception ue)
{
Response.Write(ue.Message);
}
Thanks in advance.
is there any chunk of code that could be helpful in reading the zip files bytes by bytes aur by using stream reader.
Absolutely not. StreamReader - and indeed any TextReader is for reading text content, not binary content. A zip file is not text - it's composed of bytes, not characters.
If you're reading binary content such as zip files, you should be using a Stream rather than a TextReader of any kind.
Note that WebClient.DownloadFile and WebClient.DownloadData can generally make things easier for downloading binary content.
Another simple way to downlaod zip file
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/DOWNLOAD/Filename.zip">Click To Download</asp:HyperLink>
Another solution
private void DownloadFile()
{
string getPath = "DOWNLOAD/FileName.zip";
System.IO.Stream iStream = null;
byte[] buffer = new Byte[1024];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
// Identify the file to download including its path.
string filepath = Server.MapPath(getPath);
// Identify the file name.
string filename = System.IO.Path.GetFileName(filepath);
try
{
// Open the file.
iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
// Page.Response.ContentType = "application/vnd.android.package-archive";
// Page.Response.ContentType = "application/octet-stream";
Page.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (Response.IsClientConnected)
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 1024);
// Write the data to the current output stream.
Page.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
Page.Response.Flush();
// buffer = new Byte[1024];
dataToRead = dataToRead - length;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
Page.Response.Write(ex.Message);
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
Page.Response.Close();
}
}
}
Your answer
WebRequest objRequest = System.Net.HttpWebRequest.Create(url);
objResponse = objRequest.GetResponse();
byte[] buffer = new byte[32768];
using (Stream input = objResponse.GetResponseStream())
{
using (FileStream output = new FileStream ("test.doc",
FileMode.CreateNew))
{
int bytesRead;
while ( (bytesRead=input.Read (buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
}
This is how i achieved it. Thanks everyone for ur help
Related
I'm using .NET 3.5 and I need to transfer by FTP some files.
I don't want to use files because I manage all by using MemoryStream and bytes arrays.
Reading these articles (article and article), I made my client.
public void Upload(byte[] fileBytes, string remoteFile)
{
try
{
string uri = string.Format("{0}:{1}/{2}", Hostname, Port, remoteFile);
FtpWebRequest ftp = (FtpWebRequest)WebRequest.Create(uri);
ftp.Credentials = new NetworkCredential(Username.Normalize(), Password.Normalize());
ftp.UseBinary = true;
ftp.UsePassive = true;
ftp.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream localFileStream = new MemoryStream(fileBytes))
{
using (Stream ftpStream = ftp.GetRequestStream())
{
int bufferSize = (int)Math.Min(localFileStream.Length, 2048);
byte[] buffer = new byte[bufferSize];
int bytesSent = -1;
while (bytesSent != 0)
{
bytesSent = localFileStream.Read(buffer, 0, bufferSize);
ftpStream.Write(buffer, 0, bufferSize);
}
}
}
}
catch (Exception ex)
{
LogHelper.WriteLog(logs, "Errore Upload", ex);
throw;
}
}
The FTP client connects, writes and close correctly without any error. But the written files are corrupted, such as PDF cannot be opened and for DOC/DOCX Word shows a message about file corruption and tries to restore them.
If I write to a file the same bytes passed to the Upload method, I get a correct file. So the problem must be with FTP transfer.
byte[] fileBytes = memoryStream.ToArray();
File.WriteAllBytes(#"C:\test.pdf", fileBytes); // --> File OK!
ftpClient.Upload(fileBytes, remoteFile); // --> File CORRUPTED on FTP folder!
You need to use bytesSent in the Write call:
bytesSent = localFileStream.Read(buffer, 0, bufferSize);
ftpStream.Write(buffer, 0, bytesSent);
Otherwise you write too many bytes in the last round.
I am trying to load a .gz file out of a bucket.
Connection and authentication work finde, I even do get a file, but the problem is, the file is a lot bigger then the file should be. it is, original size, 155MB within the bucket but when it comes onto my hard disk it gets up to about 288MB
here is the function code:
public bool SaveBucketToFile(string Filename)
{
//Response check into file
using (StreamReader StRead = new StreamReader(_ObjResponse.ResponseStream))
{
string TempFile = Path.GetTempFileName();
StreamWriter StWrite = new StreamWriter(TempFile, false);
StWrite.Write(StRead.ReadToEnd());
StWrite.Close();
StRead.Close();
// Move to real destination
if (File.Exists(Filename))
{
File.Delete(Filename);
}
File.Move(TempFile, Filename);
}
return true;
}
the download and filling of _ObjResponse is made over usage of the AmazonS3 Client from their SDK. I am using a proxy but the same code on a different machine without proxy brings back the same result.
Any hints what to do here? the object request is simple:
_ObjRequest = new GetObjectRequest
{
BucketName = BucketName,
Key = Key
};
glad for any help...
for everyone to stumble upon this.
I needed to first save the stream via bufferedStream into a memorystream.
the code looks like this:
MemoryStream MemStream = new MemoryStream();
BufferedStream Stream2 = new BufferedStream(_ObjResponse.ResponseStream);
byte[] Buffer = new byte[0x2000];
int Count;
while ((Count = Stream2.Read(Buffer, 0, Buffer.Length)) > 0)
{
MemStream.Write(Buffer, 0, Count);
}
// Pfad auslesen
string TempFile = Path.GetTempFileName();
//Stream zum Tempfile öffnen
FileStream Newfile = new FileStream(TempFile,FileMode.Create);
//Stream wieder auf Position 0 ziehen
MemStream.Position = 0;
// in Tempdatei speichern
MemStream.CopyTo(Newfile);
Newfile.Close();
// Endgültigen Speicherpunkt prüfen und Tempdatei dorthin schieben
if (File.Exists(Filename))
{
File.Delete(Filename);
}
File.Move(TempFile, Filename);
I found this somewhere here:
http://www.codeproject.com/Articles/186132/Beginning-with-Amazon-S under the Caption "Get a file from Amazon S3"
I have code which downloads file(zip file) from ftp server. But when I change files inside zip file, it is downloading from memory. Telling that I mean when I download zip file in which there are file 1, file 2, file 3. Next time I change zip file inside with file 1, file 2, file 3(but new data in files) and upload it to ftp. When I download from FTP directly using WS_FTP Pro I can see new files. But when I use my code to download zip file I get that file from memory. How can I refresh memory stream so when I download new zip file, I get new files inside zip file.
Mн code is.
public static bool downloadFromWeb(string URL, string file, string targetFolder)
{
try
{
byte[] downloadedData;
downloadedData = new byte[0];
//open a data stream from the supplied URL
WebRequest webReq = WebRequest.Create(URL + file);
WebResponse webResponse = webReq.GetResponse();
Stream dataStream = webResponse.GetResponseStream();
//Download the data in chuncks
byte[] dataBuffer = new byte[1024];
//Get the total size of the download
int dataLength = (int)webResponse.ContentLength;
//lets declare our downloaded bytes event args
ByteArgs byteArgs = new ByteArgs();
byteArgs.downloaded = 0;
byteArgs.total = dataLength;
//we need to test for a null as if an event is not consumed we will get an exception
if (bytesDownloaded != null) bytesDownloaded(byteArgs);
//Download the data
MemoryStream memoryStream = new MemoryStream();
memoryStream.SetLength(0);
while (true)
{
//Let's try and read the data
int bytesFromStream = dataStream.Read(dataBuffer, 0, dataBuffer.Length);
if (bytesFromStream == 0)
{
byteArgs.downloaded = dataLength;
byteArgs.total = dataLength;
if (bytesDownloaded != null) bytesDownloaded(byteArgs);
//Download complete
break;
}
else
{
//Write the downloaded data
memoryStream.Write(dataBuffer, 0, bytesFromStream);
byteArgs.downloaded = bytesFromStream;
byteArgs.total = dataLength;
if (bytesDownloaded != null) bytesDownloaded(byteArgs);
}
}
//Convert the downloaded stream to a byte array
downloadedData = memoryStream.ToArray();
//Release resources
dataStream.Close();
memoryStream.Close();
//Write bytes to the specified file
FileStream newFile = new FileStream(targetFolder + file, FileMode.Create);
newFile.Write(downloadedData, 0, downloadedData.Length);
newFile.Close();
return true;
}
catch (Exception)
{
//We may not be connected to the internet
//Or the URL may be incorrect
return false;
}
}
Please indicate me where I should change to download always new zip file from FTP.
I have added couple strings of code in my previous code. It tells browser not to cache. Here is my code with changes.
public static bool downloadFromWeb(string URL, string file, string targetFolder)
{
try
{
byte[] downloadedData;
downloadedData = new byte[0];
// Set a default policy level for the "http:" and "https" schemes.
HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Default);
HttpWebRequest.DefaultCachePolicy = policy;
//open a data stream from the supplied URL
WebRequest webReq = WebRequest.Create(URL + file);
// Define a cache policy for this request only.
HttpRequestCachePolicy noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
webReq.CachePolicy = noCachePolicy;
WebResponse webResponse = webReq.GetResponse();
Stream dataStream = webResponse.GetResponseStream();
//Download the data in chuncks
byte[] dataBuffer = new byte[1024];
//Get the total size of the download
int dataLength = (int)webResponse.ContentLength;
//lets declare our downloaded bytes event args
ByteArgs byteArgs = new ByteArgs();
byteArgs.downloaded = 0;
byteArgs.total = dataLength;
//we need to test for a null as if an event is not consumed we will get an exception
if (bytesDownloaded != null) bytesDownloaded(byteArgs);
//Download the data
MemoryStream memoryStream = new MemoryStream();
memoryStream.SetLength(0);
while (true)
{
//Let's try and read the data
int bytesFromStream = dataStream.Read(dataBuffer, 0, dataBuffer.Length);
if (bytesFromStream == 0)
{
byteArgs.downloaded = dataLength;
byteArgs.total = dataLength;
if (bytesDownloaded != null) bytesDownloaded(byteArgs);
//Download complete
break;
}
else
{
//Write the downloaded data
memoryStream.Write(dataBuffer, 0, bytesFromStream);
byteArgs.downloaded = bytesFromStream;
byteArgs.total = dataLength;
if (bytesDownloaded != null) bytesDownloaded(byteArgs);
}
}
//Convert the downloaded stream to a byte array
downloadedData = memoryStream.ToArray();
//Release resources
dataStream.Close();
memoryStream.Close();
//Write bytes to the specified file
FileStream newFile = new FileStream(targetFolder + file, FileMode.Create);
newFile.Write(downloadedData, 0, downloadedData.Length);
newFile.Close();
return true;
}
catch (Exception)
{
//We may not be connected to the internet
//Or the URL may be incorrect
return false;
}
}
I believe your get-request is being cached by the WebRequest. Try adding a random query parameter and see if it helps.
WebRequest webReq = WebRequest.Create(URL + file + "?nocache=" + DateTime.Now.Ticks.ToString());
I use Interop to SaveAs(D:/Temp) a template excel sheet after the changes are made.
Then I use FileStream to send the user a Pop-up to save this file. But that file in D:\Temp still exists.
Is there a way to delete this file on Pop-up response?
//Save the Excel File
SaveExcelFile(exportPath, sourceFile, excelWorkBook,
excelApllication, excelWorkSheet);
#region Pop Up and File Open
if (System.IO.File.Exists(sourceFile))
{
FileStream fsSource =
new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
return File(fsSource, "application/vnd.ms-excel", "FileName" + .xls");
}
else
{
return View();
}
#endregion
To delete one file
string filePath)= #"C:\MyDir\filename.txt";
public bool RemoveFile(string filePath)
{
try
{
if (File.Exists(filePath))
{
File.Delete(filePath);
return true;
}
else
return true;
}
catch (Exception ex)
{
return false;
}
}
Delete all files
string[] filePaths = Directory.GetFiles(#"c:\MyDir\");
foreach (string filePath in filePaths)
File.Delete(filePath);
To delete all files using one code line
Array.ForEach(Directory.GetFiles(#"c:\MyDir\"),
delegate(string path) { File.Delete(path); });
You can use File.Delete method.
if (File.Exists("File_Path"))
{
File.Delete("File_Path");
}
Updated
For downloading binary files,
using (FileStream fs = File.OpenRead(path))
{
int length = (int)fs.Length;
byte[] buffer;
using (BinaryReader br = new BinaryReader(fs))
{
buffer = br.ReadBytes(length);
}
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", String.Format("attachment;filename={0}", Path.GetFileName(path)));
Response.ContentType = "application/" + Path.GetExtension(path).Substring(1);
Response.BinaryWrite(buffer);
Response.Flush();
Response.End();
}
Found this code from here
Instead of creating a temp file, loading it to stream, and then trying to delete it, I suggest that you create the file directly in memory stream (i.e. System.IO.MemoryStream) in the first place, so you don't have to load it and delete it.
If you cannot create it directly in memory stream, the main issue is that you cannot delete the temp file while you're using it in the FileStream. In this case, you copy the FileStream to a MemoryStream, close and dispose the FileStream, delete the temp file, and then return the MemoryStream to the user.
You can use the function bellow to copy streams correctly.
// Author: Racil Hilan.
/// <summary>Copies data from a source stream to a target stream.</summary>
private static void CopyStream(Stream SourceStream, Stream TargetStream) {
const int BUFFER_SIZE = 4096;
byte[] buffer = new byte[BUFFER_SIZE];
//Reset the source stream in order to process all data.
if (SourceStream.CanSeek)
SourceStream.Position = 0;
//Copy data from the source stream to the target stream.
int BytesRead = 0;
while ((BytesRead = SourceStream.Read(buffer, 0, BUFFER_SIZE)) > 0)
TargetStream.Write(buffer, 0, BytesRead);
//Reset the source stream and the target stream to make them ready for any other operation.
if (SourceStream.CanSeek)
SourceStream.Position = 0;
if (TargetStream.CanSeek)
TargetStream.Position = 0;
}
You can use File.Delete() for this. Just make sure you've closed the stream before you try to delete the file, and preferably, that you have been able to send whatever you need to.
I'm guessing you don't want to delete the file if the main operation fails.
protected void downloadFunction(string filename)
{
string filepath = #"D:\XtraFiles\" + filename;
string contentType = "application/x-newton-compatible-pkg";
Stream iStream = null;
// Buffer to read 1024K bytes in chunk
byte[] buffer = new Byte[1048576];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
try
{
// Open the file.
iStream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
HttpContext.Current.Response.ContentType = contentType;
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8));
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (HttpContext.Current.Response.IsClientConnected)
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 10000);
// Write the data to the current output stream.
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
HttpContext.Current.Response.Flush();
buffer = new Byte[10000];
dataToRead = dataToRead - length;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
HttpContext.Current.Response.Write("Error : " + ex.Message + "<br />");
HttpContext.Current.Response.ContentType = "text/html";
HttpContext.Current.Response.Write("Error : file not found");
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
HttpContext.Current.Response.End();
HttpContext.Current.Response.Close();
}
}
My donwload function is working perfect, but when users are downloading the browser cant see the total file size of the download.
So now the browser says eq. Downloading 8mb of ?, insted of Downloading 8mb of 142mb.
What have i missed?
The Content-Length header seems to be what you are missing.
If you set this the browser will then know how much to expect. Otherwise it will just keep going til you stop sending data and it won't know how long it is until the end.
Response.AddHeader("Content-Length", iStream.Length);
You may also be interested in Response.WriteFile whcih can provide an easier way to send a file to a client without having to worry about streams yourself.
You need to send a ContentLength-Header:
HttpContext.Current.Response.AddHeader(HttpRequestHeader.ContentLength, iStream.Length);