【问题标题】:Upload file with HttpClient POST request returns 200, but file didn't upload使用 HttpClient POST 请求上传文件返回 200,但文件未上传
【发布时间】:2019-12-11 06:40:34
【问题描述】:

我想将 .json 文件作为文件上传到服务器。我正在使用 C# 构建一个 UWP 应用程序。我使用Windows.Web.Http.HttpClient 发出POST 请求。发布请求返回 200,但文件没有上传。该 URL 链接到公司 Web 托管平台上的文件夹。如果我检查页面或 bluehost cpanel 页面,则没有最近的文件上传与应用程序所谓的成功请求相对应。如何将文件上传到服务器?我需要提供登录凭据吗? Microsoft UWP 甚至不再支持 FTP 了吗?它真的只希望我使用HttpClient

我尝试了各种方法,但是这个(我主要从微软的用于上传简单文件的示例 C++ 代码翻译而来)是第一次它没有返回 405 或只是转储了 url 的内容。我尝试过使用HttpWebRequest 格式和System.Net.Http 前缀。

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);
}

这是httpResponseMessage 返回的内容:

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
}

但该位置没有新文件。

为了澄清,这些文件托管在 bluehost 上。如果我不能定期发布到 bluehost(就像我可以在这个网站上一样:http://ptsv2.com/t/gizn2-1564768263/d/373971039#),那么我该如何解决呢?这是一个https:// 前缀,s 是否意味着我需要 ssl 的凭据或证书?我在哪里或如何找到它?

这是 httpResponseBody 的输出,testSurveyFile.json 文件是旧文件,此上传旨在替换或覆盖。这是正确的索引。我希望这些信息能澄清一些事情。

<!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">&nbsp;</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">&nbsp;</td><td><a href="/npjTest/">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</td><td><a href="TestSurvey0/">TestSurvey0/</a>           </td><td align="right">2019-07-26 11:51  </td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</td><td><a href="vendor/">vendor/</a>                </td><td align="right">2019-07-15 07:59  </td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</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>&nbsp;</td></tr>
   <tr><th colspan="5"><hr></th></tr>
</table>
<address>Apache Server at ___________.com Port 443</address>
</body></html>

似乎我应该执行 HTTP PUT 请求而不是 POST。我已经考虑过并尝试运行 PutAsync,但我收到了与重定向相关的错误。具体来说,如果我将 AllowAutoRedirect 设置为 false(以绕过说明“HTTP 重定向请求必须由用户确认”的错误),它会返回 301 响应代码。我不确定它为什么会重定向。当我发送 uri 时,该 uri 应该转到索引 (/SurveyStuff) 还是我希望它覆盖的文件 (/SurveyStuff/testSurveyFile.json)?

如果我将 /SurveyStuff/testSurveyFile.json 结尾的 uri 用于 PUT 请求,我会收到 405(不允许)响应。我意识到这是我从一开始就应该做的,尽管我在来这里之前确实尝试过。这个响应是从 Postman 和我的应用程序返回的。出于安全目的阻止请求的是bluehost吗?我尝试了各种 FTP 和站点凭据,但没有任何作用。

【问题讨论】:

  • https:// 仅表示它使用 HTTPS 协议,是的,这意味着它需要 SSL。不过,这对您的代码并不重要。找出httpResponseBody 的值会很有趣,如果您将该行更改为httpResponseBody = await httpResponseMessage.Content.ReadAsStringAsync(); 标题表明内容类型是“text/html”,这表明您可能会得到一些有趣的响应。
  • edit您的问题包含内容...
  • 对不起,我以为我确实将输出的内容添加到了我的问题中。还有什么您需要或可能有用的吗?
  • 您的服务器端代码似乎有问题。你那里有处理上传的代码/我对bluehost一无所知;也许您必须在上传新文件之前删除旧文件/
  • 我删除了旧文件,但当我尝试通过脚本上传时,新文件并没有替换它。我不相信我已经编写了托管在服务器上的任何代码来上传 POST 请求发送的文件。我认为这个函数中的代码会进行上传。我承认,总的来说,我对 bluehost 和网络编程也很陌生。也许有一些设置阻止我从应用程序发布到 cpanel。我会再研究一下bluehost。非常感谢您的帮助。

标签: c# json http uwp


【解决方案1】:

免责声明:我必须承认我对 Windows.Web.Http.HttpClient 知之甚少。以下是一些潜在的修复方法,如果这些方法不起作用,还有其他一些解决方案。

405 问题:

  • 如果您收到 405 错误,我会仔细检查 您将其发送到并确保它是正确的,并且可以接受 POST 请求。
  • 我还会检查您是否需要 VPN 连接才能使用它 url 与否(尝试从网络浏览器中点击它)。

凭证问题: 虽然这很奇怪,因为通常您会收到 401(未经授权)错误代码,但为了安全起见,您可能希望包含凭据。

对于 System.Net.Http.HttpClient 凭据:

var httpClientHandler = new HttpClientHandler()
{
    Credentials = new NetworkCredential(username, password, domainName),
};

var httpClient = new HttpClient(httpClientHandler);

解决方案 #1:System.Net.Http.HttpClient 多部分形式的数据 (this)。

IInputStream inputStream = await file.OpenAsync(FileAccessMode.Read);

HttpMultipartFormDataContent multipartContent = new HttpMultipartFormDataContent();

multipartContent.Add(new HttpStreamContent(inputStream),"myFile",file.Name);

HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(uri,multipartContent);

解决方案 #2 System.Net.Http.HttpClient 多部分表单数据 (this)。

当他将图像作为字节数组上传时,您必须稍作调整,我建议使用更多 Using 语句,因为它们会自动处理对象。

如果您愿意,您可以将文件转换为字节数组:

byte[] bytes = System.IO.File.ReadAllBytes(filename);

解决方案 #3 如果这些方法不起作用,您可以尝试一些替代方法:

我希望这至少能让你走上正轨:)。

【讨论】:

  • 感谢您提供如此详细的帖子。我已经尝试过使用凭据,并且使用 POST 方法,它会将目标 url 的内容转储到 httpResponseMessage 调试中,并且文件仍然不会被上传。总的来说,我对 http 和 web 编程仍然相当缺乏经验。所以请原谅我问,我将如何检查 URL 是否接受 POST 请求?我在此站点link 上尝试了用于测试 POST 请求的代码,并且 json 文件显示在那里,其中包含所有正确的内容。这是什么意思?
  • 如果我错了,请纠正我,但您的 httpResponseMessage 包含正确的返回信息,只是 json 数据没有发布到网站上?如果您控制尝试发布数据内容的 Web api,则它应该在方法上方具有类似于 [HttpPost] 属性的内容。如果您无法控制它,我建议使用 Postman 尝试将一些测试 json 数据发送到您正在使用的文件服务器,看看会发生什么。如果您可以将数据发送到不同的 url,那么问题很可能出在您使用的文件服务器上。尝试使用 Postman 进行测试。
  • 我正在尝试使用 HTTP POST 上传文件。这是正确使用这种方法吗?我担心我在尝试使用它时弄错了,因为接受发布请求并回显快速调试消息的测试 .php 文件确实成功地将该消息回显到 httpResponseMessage/Body 中。我可以写一些接受 .json 数据并使用它来更新其他文件的东西,但我也想使用原始方法来上传图像。所以我仍然需要上传文件。同时,我将尝试使用 Postman 进行测试。谢谢。
  • 我使用邮递员发送带有 .json 文件的 POST 请求和一个 PUT 请求(以及一个 .txt 文件只是为了检查),但它似乎没有上传到服务器。这告诉我什么?我从客户支持那里得到的印象是 bluehost 应该支持 POST 请求,但我这边似乎没有任何问题。
  • 如果您在 Postman to Post 上执行了正确的操作,但它仍然没有显示在您的服务器上,那么问题出在服务器而不是您的代码上。您的代码可以将文件上传到不同的服务器,而不是您的服务器,这一事实进一步验证了这一点。但是,为了确保您在 Postman 上正确执行此操作,请查看此 link。同样标准的是 Post 用于创建新项目,Put 用于更新项目,通常使用 Id 发送。
【解决方案2】:

我第二次与 bluehost 支持人员交谈,这次他们说 bluehost 不支持来自任何外部来源的 HTTP POST 请求,包括 Postman。看来我需要找到另一个地方来托管这个文件。对于我在这一点上的困惑,我深表歉意。感谢您的帮助,因为它总体上提高了我对 HTTP 请求和 Web 编程的理解。非常感谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 2023-03-15
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    • 2018-12-16
    相关资源
    最近更新 更多