HttpWebRequest upload file cause The operation has timed out WebException - c#

I have been searching around for an answer but really don't know what cause my problem. I'm doing uploading a file to my server using HttpWebRequest, the scheme should be correct:
1. Compose multipart form data, boundary and trailer.
2. Set content length of request by combining length of form data, file.
3. Write directly to stream and keep track upload progress.
Here is the code I'm using:
HttpWebRequest uploadWebRequest = Func.UploadFileCompose(string.Format("url?hash={0}", uploadKeys.hash), cookieCollection);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, "video", Path.GetFileName(videoModel.DownloadedLocation), "video/mp4");
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + Func.boundary + "--\r\n");
long totalBytes = 0;
using(FileStream fileStream = new FileStream(videoModel.DownloadedLocation,FileMode.Open, FileAccess.Read))
{
totalBytes += headerbytes.Length;
totalBytes += fileStream.Length;
totalBytes += trailer.Length;
}
uploadWebRequest.ContentLength = totalBytes;
using (Stream requestStream = uploadWebRequest.GetRequestStream())
{
requestStream.ReadTimeout = 10000;
requestStream.WriteTimeout = 10000;
//write header first
requestStream.Write(headerbytes, 0, headerbytes.Length);
using (FileStream fileStream = new FileStream(videoModel.DownloadedLocation, FileMode.Open, FileAccess.Read))
{
int bytesRead = 0;
long bytesSent = 0;
byte[] buffer = new byte[1024000];
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
bytesSent += bytesRead;
requestStream.Write(buffer, 0, bytesRead);
decimal percentage = (decimal)(bytesSent * 100) / (decimal)fileStream.Length;
if (Math.Round(percentage, 1) % 0.2M == 0)
{
Func.SetProgressStatus(lvStatus, "Uploaded: " + Math.Round(percentage, 1) + "%");
}
}
}
//write trailer
requestStream.Write(trailer, 0, trailer.Length);
}
string uploadResponseInStr = "";
using (HttpWebResponse response = (HttpWebResponse)uploadWebRequest.GetResponse())
{
var encoding = ASCIIEncoding.ASCII;
try
{
using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
{
uploadResponseInStr = await reader.ReadToEndAsync();
}
}
catch (Exception e1)
{
return null;
}
}
Tried to set
req.KeepAlive = true; //true or false
req.Timeout = 10000;
req.ReadWriteTimeout = 10000;
req.ProtocolVersion = HttpVersion.Version10; // 11 or 10
Does not help.
Thanks for help in advance. Really appreciate it!
Edit: Set DefaultConnectionLimit equal 1000 does not help.
The connection have been established but it only upload a few MB before exception raised

Solved.!
This request was missing boundary and the length was incorrect.
Also it is necessary to write boundary to stream too.

Related

application/form-data in C# application?

I have using below code to upload file into url using C# console application.It doesn't upload file and not return error also.
string[] files = new string []{ "C:/test.csv" };
public static string UploadFilesToRemoteUrl(string url, string[] files, NameValueCollection formFields = null)
{
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "multipart/form-data; boundary=" +
boundary;
request.Method = "POST";
request.KeepAlive = true;
Stream memStream = new System.IO.MemoryStream();
var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "\r\n");
var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "--");
string formdataTemplate = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
if (formFields != null)
{
foreach (string key in formFields.Keys)
{
string formitem = string.Format(formdataTemplate, key, formFields[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
}
}
string headerTemplate =
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
for (int i = 0; i < files.Length; i++)
{
memStream.Write(boundarybytes, 0, boundarybytes.Length);
var header = string.Format(headerTemplate, "uplTheFile", files[i]);
var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))
{
var buffer = new byte[1024];
var bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
}
}
memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
request.ContentLength = memStream.Length;
using (Stream requestStream = request.GetRequestStream())
{
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
}
using (var response = request.GetResponse())
{
Stream stream2 = response.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
return reader2.ReadToEnd();
}
}
Upload files with HTTPWebrequest (multipart/form-data)
i have checked this code and it doesn't uploaded file in url i was given and also no error return.
This question has been answered already here:
Upload files with HTTPWebrequest (multipart/form-data)
Also, please note that in your code you are actually sending the string "C:/test.csv" and not the contents of the file! You will need to open a FileStream (https://msdn.microsoft.com/en-us/library/system.io.filestream.aspx) to stream out it's contents. (This is also covered in the answer linked above)

C#: error trying to send file to self-hosted webservice using httpwebrequest

First of all, my server is a self-hosted c# webservice. It works well for my other applications, but now I have to implement a method in it that will be used by a mobile computer with Windows CE 5. I will need to receive a file in my server, so I've written this method:
[System.ServiceModel.OperationContract, WebInvoke(UriTemplate = "test/")]
string testSaveFile(Stream arq);
public string testSaveFile(Stream img) {
Console.WriteLine("stream received");
Console.WriteLine("stream size: " + img.Length); //throws "Error 400 Bad Request"
}
And in the mobile computer, using .Net CF 3.5 I've written this method to send the file:
public static string UploadFilesToRemoteUrl( string url, string file ) {
long length = 0;
string boundary = "----------------------------" +
DateTime.Now.Ticks.ToString( "x" );
HttpWebRequest httpWebRequest2 = ( HttpWebRequest ) WebRequest.Create( url );
httpWebRequest2.AllowWriteStreamBuffering = true;
httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest2.Method = "POST";
httpWebRequest2.KeepAlive = true;
httpWebRequest2.Credentials =
System.Net.CredentialCache.DefaultCredentials;
Stream memStream = new System.IO.MemoryStream();
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes( "\r\n--"
+ boundary + "\r\n" );
memStream.Write( boundarybytes, 0, boundarybytes.Length );
length += boundarybytes.Length;
string headerTemplate = "Content-Disposition: form-data; name=\"file\";"
+" filename=\"file\"\r\n Content-Type: \"application/octet-stream\"\r\n\r\n";
string header = headerTemplate;
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes( header );
memStream.Write( headerbytes, 0, headerbytes.Length );
length += headerbytes.Length;
FileStream fileStream = new FileStream( file, FileMode.Open,
FileAccess.Read );
byte[] buffer = new byte[1024];
int bytesRead = 0;
while( ( bytesRead = fileStream.Read( buffer, 0, buffer.Length ) ) != 0 ) {
memStream.Write( buffer, 0, bytesRead );
length += bytesRead;
}
memStream.Write( boundarybytes, 0, boundarybytes.Length );
length += boundarybytes.Length;
fileStream.Close();
httpWebRequest2.ContentLength = memStream.Length;
Stream requestStream = httpWebRequest2.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read( tempBuffer, 0, tempBuffer.Length );
memStream.Close();
requestStream.Write( tempBuffer, 0, tempBuffer.Length );
requestStream.Close();
WebResponse webResponse2 = httpWebRequest2.GetResponse();
// ^ Exception here
Stream stream2 = webResponse2.GetResponseStream();
StreamReader reader2 = new StreamReader( stream2 );
string res = reader2.ReadToEnd();
webResponse2.Close();
httpWebRequest2 = null;
webResponse2 = null;
return res;
}
And using this method I am able to connect to the server. It even displays the first message ("stream received"). But whenever I try to access the stream, the server returns "Error 400 Bad Request", which appears as an exception on the mobile computer.
So how can I send a file from the mobile computer to the server? Can I fix this method or should I try another approach?
The answer to this question say to do it asynchronously but I did it and the same error is returned, and this same server is used by Android apps that do it synchronously and it works.
Thanks in advance.
One other thing: is the multipart/form-data the correct approach to send files to this webmethod?
The problem was not in the sending part. The problem was reading the stream lenghth. The answer to this question helped me.

Download a file with .net compact and C#

I am re-developing an app for a scanner used for stocktakes to allow it to work while offline. In order to do so, I need to be able to download a file from a laptop which is acting as a server. I got to a point at which it works, but only downloads that are of size 9.53mb max. How can I tweak the code to allow for larger files. I would need to allow for a maximum size of around 30mb.
Here is my code:
try
{
string full_url = App.prouductUrl + App.stStocktakeId + ".db";
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(full_url);
httpRequest.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
System.IO.Stream dataStream = httpResponse.GetResponseStream();
// Dim str As Stream = cdsMobileLibrary2.http_download.getfile(filename)
//50 meg
byte[] inBuf = new byte[10000001];
int bytesToRead = Convert.ToInt32(inBuf.Length);
int bytesRead = 0;
while (bytesToRead > 0)
{
int n = dataStream.Read(inBuf, bytesRead, bytesToRead);
if (n == 0)
{
break; // TODO: might not be correct. Was : Exit While
}
bytesRead += n;
bytesToRead -= n;
}
FileStream fstr = new FileStream(#"\productdb\" + App.stStocktakeId + ".db", FileMode.OpenOrCreate, FileAccess.Write);
fstr.Write(inBuf, 0, bytesRead);
dataStream.Close();
fstr.Close();
string size = loginRes.getFromJSON("size");
FileInfo fi = new FileInfo(#"\productdb\" + App.stStocktakeId + ".db");
MessageBox.Show("File Size is:" + fi.Length + "Compared to:" + size);
}
catch { }

ASP.Net Handler Request.Files always empty

I'm writing a C# ASP.Net application for client to post files to other server. I'm using a generic handler to handle posted files from client to server. But in my handler, context.Request.Files always empty (0 count). I believe my post method is right, because when I tried to move the handler in the same domain as the client, I can accept the files and save them. But the problem is I need to save the files to the other server.
Here is the code to post files:
private void UploadFilesToRemoteUrl3(HttpFileCollection files)
{
string url = "http://localhost:19107/Catalog/api/dashboard/ImageHandler.ashx";
long length = 0;
string boundary = "----------------------------" +
DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest2.Method = "POST";
httpWebRequest2.KeepAlive = true;
httpWebRequest2.Credentials =
System.Net.CredentialCache.DefaultCredentials;
Stream memStream = new System.IO.MemoryStream();
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
memStream.Write(boundarybytes,0,boundarybytes.Length);
length += boundarybytes.Length;
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";
foreach (string s in files)
{
HttpPostedFile file = files[s];
string header = string.Format(headerTemplate, "file", file.FileName);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes,0,headerbytes.Length);
length += headerbytes.Length;
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ( (bytesRead = file.InputStream.Read(buffer, 0, buffer.Length)) != 0 )
{
memStream.Write(buffer, 0, bytesRead);
length += bytesRead;
}
memStream.Write(boundarybytes,0,boundarybytes.Length);
length += boundarybytes.Length;
file.InputStream.Close();
}
httpWebRequest2.ContentLength = memStream.Length;
Stream requestStream = httpWebRequest2.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer,0,tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer,0,tempBuffer.Length );
requestStream.Close();
WebResponse webResponse2 = httpWebRequest2.GetResponse();
Stream stream2 = webResponse2.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
string a = reader2.ReadToEnd();
webResponse2.Close();
httpWebRequest2 = null;
webResponse2 = null;
}
And here is the code behind my handler to receive the files:
public void ProcessRequest(HttpContext context)
{
context.Request.ContentType = "multipart/form-data";
int count = context.Request.Files.Count; //always 0
foreach (string s in context.Request.Files)
{
string response = "";
HttpPostedFile file = context.Request.Files[s];
//code to save files
}
}
public Response<List<string>> UplaoadPostImage()
{
Response<List<string>> response = new Response<List<string>>();
ResponseImage objtemp = new ResponseImage();
List<string> objlist = new List<string>();
try
{
HttpContextWrapper objwrapper = GetHttpContext(this.Request);
HttpFileCollectionBase collection = objwrapper.Request.Files;
if (collection.Count > 0)
{
foreach (string file in collection)
{
HttpPostedFileBase file1 = collection.Get(file);
Stream requestStream = file1.InputStream;
Image img = System.Drawing.Image.FromStream(requestStream);
//Image UserImage = objcommon.ResizeImage(img, 600, 600);
string UniqueFileName = file1.FileName;
img.Save(HttpContext.Current.Request.PhysicalApplicationPath + "UploadImage\\" + UniqueFileName, System.Drawing.Imaging.ImageFormat.Png);
objlist.Add(ConfigurationManager.AppSettings["ImagePath"] + UniqueFileName);
requestStream.Close();
}
response.Create(true, 0, Messages.FormatMessage(Messages.UploadImage_Sucess, ""), objlist);
}
else
{
response.Create(false, 0, "File not found.", objlist);
}
}
catch (Exception ex)
{
response.Create(false, -1, Messages.FormatMessage(ex.Message), objlist);
}
return response;
}
private HttpContextWrapper GetHttpContext(HttpRequestMessage request = null)
{
request = request ?? Request;
if (request.Properties.ContainsKey("MS_HttpContext"))
{
return ((HttpContextWrapper)request.Properties["MS_HttpContext"]);
}
else if (HttpContext.Current != null)
{
return new HttpContextWrapper(HttpContext.Current);
}
else
{
return null;
}
}

PhoneGap Build API Error when Posting .ZIP file Greater than 127kb

I wrote the C# application below to update an existing application via the PhoneGap Build API. I noticed it works when my .ZIP file is 127kb or less. As soon as it hits 128kb, I get a 500 HTTP response. Sorry, the API does not return any details on the error, only the 500 response code. Any help with this issue will be greatly appreciated. Please note the placeholders for authentication token, appId and .zip file location. Thanks.
using System;
using System.IO;
using System.Net;
namespace PhoneGapBuildQuestion
{
class Program
{
static void Main(string[] args)
{
string token = "<add your token here>";
string appId = "<add your appId here>";
string zipFile = "<add full path to the application .zip file here>";
var info = new FileInfo(zipFile);
var request = (HttpWebRequest)WebRequest.Create(string.Format("https://build.phonegap.com/api/v1/apps/{0}?auth_token={1}", appId, token));
request.ContentType = "application/zip";
request.Headers["Content-disposition"] = string.Format("attachment; filename=\"{0}\"", info.Name);
request.Method = "PUT";
var reqStream = request.GetRequestStream();
var file = new FileStream(zipFile, FileMode.Open);
var bytes = new byte[32768];
int len = 0;
while((len = file.Read(bytes, 0, bytes.Length)) > 0)
reqStream.Write(bytes, 0, len);
reqStream.Close();
var response = new StreamReader(request.GetResponse().GetResponseStream());
string responseText = response.ReadToEnd();
Console.WriteLine(responseText);
Console.ReadLine();
}
}
}
I figured it out. I used fiddler to capture the request from my app and cURL, compared the two and adjusted accordingly. Here is the code I ended up with:
using System;
using System.IO;
using System.Net;
namespace PhoneGapBuildQuestion
{
class Program
{
static void Main(string[] args)
{
string appId = "[your appId here]";
string fileName = "[absolute path to .zip file here]";
string token = "[authentication token here]";
string boundry = "----------------------------7b053ae48e94";
var encoding = new System.Text.ASCIIEncoding();
var fileInfo = new FileInfo(fileName);
var ms = new MemoryStream();
long totalBytes = 0;
string txt = string.Format("--{0}{2}Content-Disposition: form-data; name=\"file\"; filename=\"{1}\"{2}Content-Type: application/octet-stream{2}{2}", boundry, fileInfo.Name, Environment.NewLine);
int bytesRead = 0;
var buffer = new byte[32768];
bytesRead = encoding.GetBytes(txt, 0, txt.Length, buffer, 0);
totalBytes += bytesRead;
ms.Write(buffer, 0, bytesRead);
// read/write file contents to the stream
var fs = new FileStream(fileName, FileMode.Open);
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, bytesRead);
totalBytes += bytesRead;
}
txt = Environment.NewLine + "--" + boundry + "--" + Environment.NewLine;
bytesRead = encoding.GetBytes(txt, 0, txt.Length, buffer, 0);
totalBytes += bytesRead;
ms.Write(buffer, 0, bytesRead);
ms.Position = 0;
var request = (HttpWebRequest)WebRequest.Create(string.Format("https://build.phonegap.com/api/v1/apps/{0}?auth_token={1}", appId, token));
request.ContentLength = totalBytes;
request.Method = "PUT";
request.ContentType = "multipart/form-data; boundary=" + boundry;
var requestStream = request.GetRequestStream();
while ((bytesRead = ms.Read(buffer, 0, buffer.Length)) > 0)
requestStream.Write(buffer, 0, bytesRead);
requestStream.Close();
Console.WriteLine(new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd());
Console.ReadLine();
}
}
}

Categories