I want to upload a .json file to a server as a file. I am building a UWP app using C#. I make the POST request using Windows.Web.Http.HttpClient
. The post request returns 200, but the file didn’t upload. The URL links to a folder on the company’s web hosting platform. If I check the page or the bluehost cpanel page, there are no recent file uploads to correspond with the app’s supposedly successful request. How do I upload a file to the server? Do I need to provide login credentials? Does Microsoft UWP even support FTP anymore? It really only wants me to use HttpClient
.
I’ve tried various methods, but this one (which I mostly translated from Microsoft’s example C++ code for uploading a simple file) is the first time it hasn’t returned a 405 or just dumped the contents of the url. I have tried using the HttpWebRequest
format and the System.Net.Http
prefix.
fileOpenPicker.FileTypeFilter.Add(".json");
IStorageFile jsonFile = await fileOpenPicker.PickSingleFileAsync();
IRandomAccessStream stream = await jsonFile.OpenAsync(FileAccessMode.Read);
Windows.Web.Http.HttpStreamContent jsonContent = new HttpStreamContent(stream);
jsonContent.Headers.Append("Content-Type", "application/json");
Windows.Web.Http.Headers.HttpContentDispositionHeaderValue disposition = new Windows.Web.Http.Headers.HttpContentDispositionHeaderValue("form-data");
jsonContent.Headers.ContentDisposition = disposition;
disposition.Name ="fileForUpload";
disposition.FileName = "testSurveyFile.json";
Windows.Web.Http.HttpMultipartFormDataContent postContent = new HttpMultipartFormDataContent();
postContent.Add(jsonContent); // Add the binary data content as a part of the form data content.
Windows.Web.Http.HttpResponseMessage httpResponseMessage;
string httpResponseBody;
try
{
// Send the POST request.
Uri requestUri = new Uri(uploadurl);
Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();
httpResponseMessage = await httpClient.PostAsync(requestUri, postContent);
httpResponseMessage.EnsureSuccessStatusCode();
Debug.WriteLine(httpResponseMessage);
httpResponseBody = httpResponseMessage.Content.ReadAsStringAsync().GetResults();
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
This is what httpResponseMessage
returns:
StatusCode: 200,
ReasonPhrase: '',
Version: 3,
Content: Windows.Web.Http.HttpStreamContent,
Headers:
{
server: nginx/1.14.1
cache-control: no-store, no-cache, must-revalidate
set-cookie: PHPSESSID=4f21dec8695cea2b75d009c47d9b94bb; path=/
date: Fri, 02 Aug 2019 15:28:34 GMT
pragma: no-cache
}{
content-type: text/html; charset=UTF-8
expires: Thu, 19 Nov 1981 08:52:00 GMT
}
but there is no new file at the location.
To clarify, the files are hosted on bluehost. If I can’t POST to bluehost regularly (like I can with this site: http://ptsv2.com/t/gizn2-1564768263/d/373971039#) then how do I get around that? It is an https://
prefix, does the s mean I need credentials or certifications for ssl? Where or how could I find that out?
This is the output of httpResponseBody, the testSurveyFile.json file is an old one this upload is meant to replace or overwrite. This is the correct index. I hope this information clears some things up.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Index of /npjTest/SurveyStuff</title>
</head>
<body>
<h1>Index of /npjTest/SurveyStuff</h1>
<table>
<tr><th valign="top"> </th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
<tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"> </td><td><a href="/npjTest/">Parent Directory</a> </td><td> </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="TestSurvey0/">TestSurvey0/</a> </td><td align="right">2019-07-26 11:51 </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="blankHTMLPage.html">blankHTMLPage.html</a> </td><td align="right">2019-07-22 10:25 </td><td align="right">4.7K</td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="composer.json">composer.json</a> </td><td align="right">2019-07-15 08:00 </td><td align="right"> 60 </td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="composer.lock">composer.lock</a> </td><td align="right">2019-07-15 08:00 </td><td align="right">2.2K</td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="error_log">error_log</a> </td><td align="right">2019-07-31 09:19 </td><td align="right">9.5K</td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="surveyConfig.php">surveyConfig.php</a> </td><td align="right">2019-07-30 10:12 </td><td align="right">675 </td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="surveyFinalPage.php">surveyFinalPage.php</a> </td><td align="right">2019-07-31 14:35 </td><td align="right"> 12K</td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="surveyLogic.php">surveyLogic.php</a> </td><td align="right">2019-07-31 14:34 </td><td align="right">9.8K</td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="testSurveyFile.json">testSurveyFile.json</a> </td><td align="right">2019-07-31 14:37 </td><td align="right">4.0K</td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="testSurveyPage.html">testSurveyPage.html</a> </td><td align="right">2019-07-22 12:18 </td><td align="right">4.7K</td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="vendor/">vendor/</a> </td><td align="right">2019-07-15 07:59 </td><td align="right"> - </td><td> </td></tr>
<tr><td valign="top"> </td><td><a href="vendorZIP2.zip">vendorZIP2.zip</a> </td><td align="right">2019-07-15 07:58 </td><td align="right">2.6M</td><td> </td></tr>
<tr><th colspan="5"><hr></th></tr>
</table>
<address>Apache Server at ___________.com Port 443</address>
</body></html>
It seems like I should be doing an HTTP PUT request instead of a POST. I had considered it and tried running PutAsync instead, but I’m getting errors related to redirects. Specifically, if I turn AllowAutoRedirect to false (to bypass an error stating that ‘The HTTP redirect request must be confirmed by the user’) it comes back with a 301 response code. I’m not sure why it’s redirecting. When I send the uri, should that uri go to the index (/SurveyStuff) or the file I want it to overwrite (/SurveyStuff/testSurveyFile.json)?
If I use the uri ending in /SurveyStuff/testSurveyFile.json for a PUT request I get a 405 (Not Allowed) response. I realize this what I should have been doing from the beginning, though I did try it before coming here. This response is returned from both Postman and my app. Is it bluehost that’s blocking the request for security purposes? I’ve tried various FTP and site credentials, but they haven’t made a difference.
2
Answers
I spoke with bluehost support for a second time, and this time they said bluehost does not support HTTP POST requests from any external source, including Postman. It seems I'll need to find another place to host this file. I apologize for my confusion on this point. I appreciate the help, as it improved my understanding of HTTP requests and web programming in general. Thank you very much.
Disclaimer: I must admit I know very little about Windows.Web.Http.HttpClient. Here are some potential fixes, and if those don’t work, some other solutions.
405 Issue:
you are sending it to and make sure it’s correct, and can accept POST
requests.
url or not (try to hit it from a web browser).
Credential Issue:
Although this would be odd, because usually you would receive a 401 (unauthorized) error code, you might want to include credentials just to be safe.
Review if you want to be using Windows.Web.Http.HttpClient or
System.Net.Http.HttpClient(differences).
For Windows.Web.Http.HttpClient.
For System.Net.Http.HttpClient Credentials:
Solution #1: System.Net.Http.HttpClient multipart-form data (this).
Solution #2 System.Net.Http.HttpClient multipart-form data (this).
You’ll have to tweak this a bit as he is uploading an image as a byte array, and I would suggest using more Using statements as they automatically dispose the object.
You could convert your file to a byte array if you wish:
Solution #3 If those do not work, you can try some alternative methods:
I hope this at least puts you on the right track :).