I am using and API that accepts an image file and returns a JSON string as a response on console C# application. I am sending the image to the API using HTTP POST method and I keep getting an error message from the server saying: The remote server returned an error: (500) Internal Server Error. No specified file in the request body, the code I wrote so far:
public static void HttpUploadFile(string url, string file, string paramName, string contentType)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length-1);
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)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
Console.WriteLine(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
Console.ReadKey();
}
catch (WebException ex)
{
Console.WriteLine("Error uploading file "+ ex);
WebResponse errResp = ex.Response;
Console.ReadKey();
using (Stream respStream = errResp.GetResponseStream())
{
StreamReader reader = new StreamReader(respStream);
string text = reader.ReadToEnd();
Console.WriteLine(text);
Console.ReadKey();
}
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
I am sending to this method the following parameters from the main:
HttpUploadFile(URL,
#"SomeImage.jpg", "file", "image/jpg");
The Image location is in the solution's directory: Project/bin/debug.
The exact error message :
Error uploading file System.Net.WebException: The remote server returned an error: (500) Internal Server Error.
at System.Net.HttpWebRequest.GetResponse()
{"code": 500,"error": "Invalid Request - No file specified in the request body"}
I looked all over the internet for similar issues but couldn't find a solution for the problem, does anyone know what might be the error? or have any assumptions?
Related
I've seen many different 'answers' to this, none of them complete. This is my current code for my upload function. It should be complete enough for discussion. I'm getting a (500) error when attempting to upload a .png file. The .png file gets consumed by the formbytes stream, but when it gets to the actual request on the last line, it throws the error. HELP!
public void Upload(string uri, string filePath)
{
FileInfo fi = new FileInfo(filePath);
string fileType = fi.Extension.Replace(".", "");
string slug = fi.Name.Replace(fi.Extension, "");
string formdataTemplate = "Content-Disposition: form-data; name=\"file\" filename=\"{0}\";\r\nContent-Type: application/octet-stream\r\n\r\n";
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Accept = "application/json";
if (cookies != null)
{
// cookies is a cookie container populated by another process, works for creating ALM requirements
request.CookieContainer = cookies;
}
request.Headers.Add("slug", slug);
string formitem = "";
byte[] formbytes = null;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(boundarybytes, 0, boundarybytes.Length);
formitem = string.Format(formdataTemplate, Path.GetFileName(filePath));
formbytes = Encoding.UTF8.GetBytes(formitem);
requestStream.Write(formbytes, 0, formbytes.Length);
byte[] buffer = new byte[1024 * 4];
int bytesLeft = 0;
while ((bytesLeft = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
requestStream.Write(buffer, 0, bytesLeft);
}
}
}
//request.Headers.Add(formbytes);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { }
}
The answer is that I had to check-out the requirement to add the attachment. It's a simple post, with no body needed, to :
/rest/domains/[domain]/projects/[project]/requirements/[entityId]/versions/check-out
and you can check-in, also no body needed:
/rest/domains/[domain]/projects/[project]/requirements/[entityId]/versions/check-out
I try to Send Multipart Content as a Post to an WebService using c# HttpClient
My Code is the Following
public string UploadDocument(Stream stream)
{
MultipartContent multipart = new MultipartContent();
//multipart.Add(new StreamContent(stream), "importFile");
StreamContent content = new StreamContent(stream);
multipart.Add(content);
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = Client.PostAsync("URL to webservice", multipart).Result;
string result = response.Content.ReadAsStringAsync().Result;
//Wirft eine Exception wenn der StatusCode nicht 200 (OK) ist.
response.EnsureSuccessStatusCode();
return result;
}
I Need the Stream Content to be named, how can i do it.
I found a Java Way to do it, but in C# I don't find a Parameter "Name"
Here the Java Example (see "importFile")
httpRequest = new HttpPostwebviewer/?action=import");
// set headers
httpRequest.setHeader(HEADER_NAME_ACCEPT, "application/json");
// prepare upload entity
MultipartEntityBuilder meBuilder = MultipartEntityBuilder.create();
meBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
meBuilder.setCharset(Consts.UTF_8);
meBuilder.addPart("importFile", contentBody);
// build upload entity
HttpEntity uploadEntity = meBuilder.build();
// set properties to http request
((HttpPost) httpRequest).setEntity(uploadEntity);
You can use System.Net.HttpWebRequest to do the same, Below is the code that I am using:
public static void UploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
url = handlerLocation + url;
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, 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.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
}
catch (Exception ex)
{
//WriteTrace(ex.Message);
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
(i'm french, sorry for my english)
I don't find / understand how send a simple PDF file by post request at a webService (REST protocol).
I tried some examples but it's doesn't word. And when i use a , it's work, but i want do this in the code behind only !
My question is the title : How send this PDF file?
The url : https://test.website.fr/Website/api/transactions/" + sVal + "/contrat
PDF file : questions.pdf
Thanks.
Iris Touchard
I found the solution :
//Identificate separator
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
//Encoding
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
//Creation and specification of the request
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create("https://test.website.fr/Website/api/transactions/" + sVal + "/contrat"); //sVal is id for the webService
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
string sAuthorization = "login:password";//AUTHENTIFICATION BEGIN
byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(sAuthorization);
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
wr.Headers.Add("Authorization: Basic " + returnValue); //AUTHENTIFICATION END
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; //For the POST's format
//Writting of the file
rs.Write(boundarybytes, 0, boundarybytes.Length);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(Server.MapPath("questions.pdf"));
rs.Write(formitembytes, 0, formitembytes.Length);
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, "file", "questions.pdf", contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(Server.MapPath("questions.pdf"), 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.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
rs = null;
WebResponse wresp = null;
try
{
//Get the response
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
string responseData = reader2.ReadToEnd();
}
catch (Exception ex)
{
string s = ex.Message;
}
finally
{
if (wresp != null)
{
wresp.Close();
wresp = null;
}
wr = null;
}
This should be what you are looking for:
http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
Here's a quick code example:
byte[] pdfFile = File.ReadAllBytes("pdf file path here");
WebRequest request = WebRequest.Create("https://test.site.fr/Testfile");
request.Method = "POST";
request.ContentLength = pdfFile.Length;
request.ContentType = "application/pdf";
Stream stream = request.GetRequestStream();
stream.Write(pdfFile, 0, pdfFile.Length);
stream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
Console.WriteLine(reader.ReadToEnd());
reader.Close();
I followed another question about posting a file to a remote url: Upload files with HTTPWebrequest (multipart/form-data)
It is making the remote url crash in my HttpHandler with: "Unable to cast object of type 'System.String' to type 'System.Web.HttpPostedFile'." Is the method posting the right file data, or is it posting just a string?
This is the method that is used to post the file to the remote server:
public void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
Response.Write(string.Format("Uploading {0} to {1}", file, url));
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
var wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
var rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
var fileStream = new FileStream(file, 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.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
var stream2 = wresp.GetResponseStream();
var reader2 = new StreamReader(stream2);
Response.Write(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
}
catch (Exception ex)
{
Response.Write("Error uploading file: " + ex.Message);
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
This is the HttpHandler on the remote server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections.Specialized;
namespace SitefinityWebApp.Widgets.Files
{
public class UploadFileHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
//VALIDATE FILES IN REQUEST
if (context.Request.Files.Count > 0)
{
try
{
//HANDLE EACH FILE IN THE REQUEST
foreach (HttpPostedFile item in context.Request.Files)
{
item.SaveAs(context.Server.MapPath("~/Temp/" + item.FileName));
context.Response.Write("File uploaded");
}
}
catch (Exception ex)
{
//NO FILES IN REQUEST TO HANDLE
context.Response.Write("Error: " + ex.Message);
}
}
else
{
//NO FILES IN REQUEST TO HANDLE
context.Response.Write("No file uploaded");
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
And this is how you use the HttpUploadFile method:
var nvc = new NameValueCollection();
nvc.Add("user", userName);
nvc.Add("password", password);
nvc.Add("library", libraryName);
HttpUploadFile(destinationUrl, uploadFile, "file", "image/png", nvc);
Iterating through the HttpFileCollection will return only the file keys. So you have to change your HTTP handler as follow:
//HANDLE EACH FILE IN THE REQUEST
foreach (string key in context.Request.Files)
{
HttpPostedFile item = context.Request.Files[key];
item.SaveAs(context.Server.MapPath("~/Temp/" + item.FileName));
context.Response.Write("File uploaded");
}
Hope, this helps.
I am trying to POST an attachment to CouchDB using the HttpWebRequest. However, when I attempt "response = (HttpWebResponse)httpWebRequest.GetResponse();" I receive a WebException with the message "The underlying connection was closed: A connection that was expected to be kept alive was closed by the server."
I have found some articles stating that setting the keepalive to false and httpversion to 1.0 resolves the situation. I am finding that it does not yeilding the exact same error, plus I do not want to take that approach as I do not want to use the 1.0 version due to how it handles the connection.
Any suggestions or ideas are welcome. I'll try them all until one works!
public ServerResponse PostAttachment(Server server, Database db, Attachment attachment)
{
Stream dataStream;
HttpWebResponse response = null;
StreamReader sr = null;
byte[] buffer;
string json;
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
string headerTemplate = "Content-Disposition: form-data; name=\"_attachments\"; filename=\"" + attachment.Filename + "\"\r\n Content-Type: application/octet-stream\r\n\r\n";
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(headerTemplate);
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://" + server.Host + ":" +
server.Port.ToString() + "/" + db.Name + "/" + attachment.Document.Id);
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest.Method = "POST";
httpWebRequest.KeepAlive = true;
httpWebRequest.ContentLength = attachment.Stream.Length + headerbytes.Length + boundarybytes.Length;
if (!string.IsNullOrEmpty(server.EncodedCredentials))
httpWebRequest.Headers.Add("Authorization", server.EncodedCredentials);
if (!attachment.Stream.CanRead)
throw new System.NotSupportedException("The stream cannot be read.");
// Get the request stream
try
{
dataStream = httpWebRequest.GetRequestStream();
}
catch (Exception e)
{
throw new WebException("Failed to get the request stream.", e);
}
buffer = new byte[server.BufferSize];
int bytesRead;
dataStream.Write(headerbytes,0,headerbytes.Length);
attachment.Stream.Position = 0;
while ((bytesRead = attachment.Stream.Read(buffer, 0, buffer.Length)) > 0)
{
dataStream.Write(buffer, 0, bytesRead);
}
dataStream.Write(boundarybytes, 0, boundarybytes.Length);
dataStream.Close();
// send the request and get the response
try
{
response = (HttpWebResponse)httpWebRequest.GetResponse();
}
catch (Exception e)
{
throw new WebException("Invalid response received from server.", e);
}
// get the server's response json
try
{
dataStream = response.GetResponseStream();
sr = new StreamReader(dataStream);
json = sr.ReadToEnd();
}
catch (Exception e)
{
throw new WebException("Failed to access the response stream.", e);
}
// close up all our streams and response
sr.Close();
dataStream.Close();
response.Close();
// Deserialize the server response
return ConvertTo.JsonToServerResponse(json);
}
After a considerable amount of research on the topic, I have decided to use PUT. While Futon uses the POST method, it is undocumented. For anyone reading this in the future, use the PUT method, it will make your life much easier.