sending httpresponses in library file c# - c#

i used the following code to download the file folder in asp.net website are
string path = #"E:\sample.zip";
FileInfo file = new FileInfo(path);
int len = (int)file.Length, bytes;
Response.ContentType = "text/html";
// Response.AddHeader "Content-Disposition", "attachment;filename=" + filename;
Response.AppendHeader("content-length", len.ToString());
byte[] buffer = new byte[1024];
using(Stream stream = File.OpenRead(path)) {
while (len > 0 && (bytes =
stream.Read(buffer, 0, buffer.Length)) > 0)
{
Response.OutputStream.Write(buffer, 0, bytes);
len -= bytes;
}
}
it works fine/...
but my problem is when i used the same code to the library file as
FileInfo file = new FileInfo(ZipPath);
int len = (int)file.Length, bytes;
HttpResponse Response = new HttpResponse(TextWriter.Null);
Response.ContentType = "text/html";
Response.AppendHeader("content-length", len.ToString());
byte[] buffer = new byte[1024];
using (Stream stream = File.OpenRead(ZipPath))
{
while (len > 0 && (bytes =
stream.Read(buffer, 0, buffer.Length)) > 0)
{
Response.OutputStream.Write(buffer, 0, bytes);
len -= bytes;
}
}
}
it throws me a error as
OutputStream is not available when a custom TextWriter is used.
i guess the problem is in that line
HttpResponse Response = new HttpResponse(TextWriter.Null);
can you provide me a solution
waiting for your responses....

You can try with this code
TextWriter sw = new StringWriter();
HttpResponse Response = new HttpResponse(sw);

i replaced the structures as
HttpResponse response = HttpContext.Current.Response;
it works fine.....
Thanks all for your support

Related

Reading data from System.IO.Stream to text or a file

I am using HttpWebRequest.GetStreamData() to get data from stream and then writing a couple of files in that variable.
Before calling the GetResponse() method on the stream, I need to get the copy of data and put it in text format.
Here's my code snippet
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.Method = "POST";
string requestbody = "Some Body Text"
Stream rs = wr.GetRequestStream();
foreach (fragment in Documents).ToList())
{
byte[] requestBytes = System.Text.Encoding.UTF8.GetBytes(requestbody);
rs.Write(requestBytes, 0, requestBytes.Length);
FileStream fileStream = new FileStream(fragment.FilePath, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Flush();
fileStream.Close();
fileStream = null;
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("Trailer Text");
rs.Write(trailer, 0, trailer.Length);
}
}
using (StreamReader strm = new StreamReader(rs))
{
string text = strm.ReadToEnd();
}
rs.Close();
rs = null;
The issue is I get error "stream was not readable".
When I check the property rs.canread, it is set to false.
Can anyone help me reading the content of my rs stream.
I have tried a couple of methods but none seems to be working as of now.

The stream does not support concurrent IO read or write operations

I have tried to search for this issue else where in Stack Overflow but couldn't find a proper answer, hence posting my question here. Below is my code, basically i am trying to read content from a file and post it to a web api, and then repeat the same step with another file. The first call passes but the second call fails with the error:
The stream does not support concurrent IO read or write operations at this line requestStream.Write(buffer, 0, bytesRead);.
Could please tell me what am i doing wrong here?
using(FileStream fs = new FileStream(# "C:\Test1.txt", FileMode.Open, FileAccess.Read)) {
byte[] buffer = null;
int bytesRead = 0;
using(Stream requestStream = request.GetRequestStream()) {
buffer = new Byte[checked((uint) Math.Min(1024, (int) fs.Length))];
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0) {
requestStream.Write(buffer, 0, bytesRead);
}
requestStream.Flush();
}
}
using(FileStream fs = new FileStream(# "C:\Test2.txt", FileMode.Open, FileAccess.Read)) {
byte[] buffer = null;
int bytesRead = 0;
using(Stream requestStream = request.GetRequestStream()) {
buffer = new Byte[checked((uint) Math.Min(1024, (int) fs.Length))];
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0) {
requestStream.Write(buffer, 0, bytesRead);
}
requestStream.Flush();
}
}
I believe the problem is happening because you are trying to get a request stream that is no more avaliable:
Try this code:
List<string> files = new List<String>();
files.Add(#"C:\Test1.txt");
files.Add(#"C:\Test2.txt");
using (Stream requestStream = request.GetRequestStream())
{
files.ForEach(fileName =>
{
byte[] buffer = null;
int bytesRead = 0;
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
buffer = new Byte[checked((uint)Math.Min(1024, (int)fs.Length))];
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
}
requestStream.Flush();
}
});
}
Update: To have control over endpoints and files, try this:
static void Main(string[] args)
{
string result = SendPost(#"C:\Test1.txt", "https://httpbin.org/post");
if(result.Contains("SUCCESS"))
SendPost(#"C:\Test2.txt", "https://httpbin.org/anotherpost");
}
static string SendPost(string filename, string URL)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(URL);
httpWebRequest.ContentType = "text/plain";
httpWebRequest.Method = "POST";
/*proxy config*/
WebProxy proxy = new WebProxy();
Uri newUri = new Uri("http://xxxxxx");
proxy.Address = newUri;
httpWebRequest.Proxy = proxy;
using (var sw = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string[] lines = File.ReadAllLines(filename);
for(int i=0; i<lines.Length; i++)
sw.WriteLine(lines[i]);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}

How do I download a file using to the downloads folder with response.WriteResponseStreamToFile? (Amazon S3, C#)

I have some PDFs stored in S3 and I'm trying to make a link that will download them. This is the method that I have so far:
public virtual ActionResult DownloadPDF(string filename)
{
string secretKey = this.UnitOfWork.ApplicationSettingRepository.GetOrCreateByName<string>("StorageProvider_AmazonS3_SecretKey");
string accessKey = this.UnitOfWork.ApplicationSettingRepository.GetOrCreateByName<string>("StorageProvider_AmazonS3_AccessKey");
var bucket = this.UnitOfWork.ApplicationSettingRepository.GetOrCreateByName<string>("StorageProvider_AmazonS3_BucketName");
var serviceUrl = this.UnitOfWork.ApplicationSettingRepository.GetOrCreateByName<string>("StorageProvider_AmazonS3_ServiceUrl");
AmazonS3Config config = new AmazonS3Config();
config.ServiceURL = serviceUrl;
var client = Amazon.AWSClientFactory.CreateAmazonS3Client(
accessKey,
secretKey,
config
);
GetObjectRequest request = new GetObjectRequest();
request.BucketName = bucket;
request.Key = "userfiles/MSD IMAGES/ProductDocumentation/" + filename;
GetObjectResponse response = client.GetObject(request);
response.WriteResponseStreamToFile("\\Downloads\\" + filename);
}
I got that method from this documentation here but I want to download the download to show in the browser, and go to the standard downloads folder. I created this method previously for downloading csv files:
var csv = new StringBuilder();
csv.AppendLine("col1,col2,col3");
var bytes = Encoding.UTF8.GetBytes(csv.ToString());
var response = new FileContentResult(bytes, "text/csv");
response.FileDownloadName = fileName;
return response;
I tried doing the same thing with the S3 file:
GetObjectResponse response = client.GetObject(request);
// response.WriteResponseStreamToFile("\\Downloads\\" + filename);
var bytes = Encoding.UTF8.GetBytes(response.ToString());
var download = new FileContentResult(bytes, "application/pdf");
download.FileDownloadName = filename;
return download;
it downloads a file, but the pdf doesn't work (it fails to load). How do I download the file that I got from S3?
Here's the working solution I came up with:
GetObjectResponse response = client.GetObject(request);
using (Stream responseStream = response.ResponseStream)
{
var bytes = ReadStream(responseStream);
var download = new FileContentResult(bytes, "application/pdf");
download.FileDownloadName = filename;
return download;
}
public static byte[] ReadStream(Stream responseStream)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
you would need to do something like the following
int byteCount
byte[] buffer = new byte[2048]; // read in chunks of 2KB
Stream responseStream= Response.GetResponseStream();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
while ((byteCount = responseStream.Read(buffer, 0, buffer.Length)) > 0)
{
Response.OutputStream.Write(buffer, 0, byteCount);
}
Response.Flush();
Response.Close();
Response.End();

Transfer really large files using WebClient

My requirement is to transfer a zip file of size 400MB or more; The following code works for at least 40MB; But for more I would have to change byte[] bytes = new byte[50000000]; to byte[] bytes = new byte[400000000]; and maxRequestLength to maxRequestLength="409600";
The problem is byte[] bytes = new byte[100000000]; returns an error regarding insufficient space. So how can I transfer large files using WebClient??
WebClient client = new WebClient();
client.AllowWriteStreamBuffering = true;
UriBuilder ub = new UriBuilder("http://localhost:57596/UploadImages.ashx");
ub.Query = "ImageName=" + "DataSet" + DataSetId + ".zip";
client.OpenWriteCompleted += (InputStream, eArguments) =>
{
try
{
using (Stream output = eArguments.Result)
{
output.Write(ImagesAux, 0, (int)ImagesAux.Length);
//numeroimagem++;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
//throw;
}
};
client.OpenWriteAsync(ub.Uri);
in UploadImages.ashx
public void ProcessRequest(HttpContext context)
{
//context.Response.ContentType = "text/plain";
//context.Response.Write("Hello World");
string ImageName = context.Request.QueryString["ImageName"];
string UploadPath = context.Server.MapPath("~/ServerImages/");
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[50000000]; //
int bytesToRead = 0;
while ((bytesToRead =
context.Request.InputStream.Read(bytes, 0, bytes.Length)) != 0)
{
stream.Write(bytes, 0, bytesToRead);
stream.Close();
}
}
}
in Web.config
<httpRuntime targetFramework="4.5" maxRequestLength="40960"/>
You should never load everything in memory then write all back to disk, but instead you should load pieces and write them to disk while you are reading them.
When you've done reading you close the stream you are writing to.
Otherwise as soon as you reach sizes as GB you can get an OutOfMemory really quick.
So I would change the writing bytes to disk from this:
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[50000000]; //
int bytesToRead = 0;
while ((bytesToRead = context.Request.InputStream.Read(bytes, 0, bytes.Length)) != 0)
{
stream.Write(bytes, 0, bytesToRead);
stream.Close();
}
}
to this:
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[1024];
long totalBytes = context.Request.InputStream.Length;
long bytesRead = 0;
int bytesToRead = bytes.Length;
if (totalBytes - bytesRead < bytes.Length)
bytesToRead = (int)(totalBytes - bytesRead);
bytes = new byte[bytesToRead];
while ((bytesToRead = context.Request.InputStream.Read(bytes, bytesRead, bytes.Length)) != 0)
{
stream.Write(bytes, bytesRead, bytes.Length);
bytesRead += bytes.Length;
if (totalBytes - bytesRead < bytes.Length)
bytesToRead = (int)(totalBytes - bytesRead);
bytes = new byte[bytesToRead];
}
stream.Close();
}
1024 would be the buffer size.

Download a file and read from it in the same time

I download a file with this method:
WebClient WC = new WebClient();
WC.DownloadFile(url, filePath);
And i want that in the same time to read the file in the same time with:
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
but i get allways :
The process cannot access the file 'filePath' because it is being used by another process.
It's possible to download and read in the same time?
Edit
I now download the file with:
var req = (HttpWebRequest)HttpWebRequest.Create(url);
var fileStream = new FileStream(filePath,
FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
using (var resp = req.GetResponse())
{
using (var stream = resp.GetResponseStream())
{
byte[] buffer = new byte[0x10000];
int len;
while ((len = stream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, len);
}
}
}
And still get the error....
var req = (HttpWebRequest)HttpWebRequest.Create(url);
using (var resp = req.GetResponse())
{
using (var stream = resp.GetResponseStream())
{
byte[] buffer = new byte[0x10000];
int len;
while ((len = stream.Read(buffer, 0, buffer.Length))>0)
{
//Do with the content whatever you want
// ***YOUR CODE***
fileStream.Write(buffer, 0, len);
}
}
}
Try this way :
HttpWebRequest request = (HttpWebRequest) WebRequest.Create("http://www.domain.com/file.txt");
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
var stream = response.GetResponseStream();
byte[] buffer = new byte[8192];
int bytesRead = 0;
while ((bytesRead = stream.Read(buffer, 0, 8192)) > 0)
{
// handle your raw data
// you needed raw data = buffer[0 to bytesRead - 1]
}
stream.Close();
response.Close();

Categories

Resources