【问题标题】:The remote server returned an error: (400) Bad Request - uploading less 2MB file size?远程服务器返回错误:(400) 错误请求 - 上传小于 2MB 的文件?
【发布时间】:2012-03-14 10:36:42
【问题描述】:

当文件大小为 2KB 或更低时,文件成功上传。我使用流媒体的主要原因是能够上传至少 1 GB 的文件。但是当我尝试上传小于 1MB 的文件时,我收到了错误的请求。这是我第一次处理下载和上传过程,所以我不能轻易找到错误原因。

测试部分:

private void button24_Click(object sender, EventArgs e)
{
    try
    {
        OpenFileDialog openfile = new OpenFileDialog();
        if (openfile.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            string port = "3445";
            byte[] fileStream;
            using (FileStream fs = new FileStream(openfile.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                fileStream = new byte[fs.Length];
                fs.Read(fileStream, 0, (int)fs.Length);
                fs.Close();
                fs.Dispose();
            }

            string baseAddress = "http://localhost:" + port + "/File/AddStream?fileID=9";
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(baseAddress);
            request.Method = "POST";
            request.ContentType = "text/plain";
            //request.ContentType = "application/octet-stream";
            Stream serverStream = request.GetRequestStream();
            serverStream.Write(fileStream, 0, fileStream.Length);
            serverStream.Close();
            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                int statusCode = (int)response.StatusCode;
                StreamReader reader = new StreamReader(response.GetResponseStream());
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}  

服务:

[WebInvoke(UriTemplate = "AddStream?fileID={fileID}", Method = "POST", BodyStyle = WebMessageBodyStyle.Bare)]
public bool AddStream(long fileID, System.IO.Stream fileStream)
{
    ClasslLogic.FileComponent svc = new ClasslLogic.FileComponent();
    return svc.AddStream(fileID, fileStream);
}  

流式传输服务器代码:

namespace ClasslLogic
{
    public class StreamObject : IStreamObject
    {
        public bool UploadFile(string filename, Stream fileStream)
        {
            try
            {
                FileStream fileToupload = new FileStream(filename, FileMode.Create);
                byte[] bytearray = new byte[10000];
                int bytesRead, totalBytesRead = 0;
                do
                {
                    bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
                    totalBytesRead += bytesRead;
                } while (bytesRead > 0);

                fileToupload.Write(bytearray, 0, bytearray.Length);
                fileToupload.Close();
                fileToupload.Dispose();
            }
            catch (Exception ex) { throw new Exception(ex.Message); }
            return true;
        }
    }
}  

网络配置:

<system.serviceModel>
<bindings>
  <basicHttpBinding>
    <binding>
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="2097152" maxBytesPerRead="4096" maxNameTableCharCount="2097152" />
      <security mode="None" />
    </binding>
    <binding name="ClassLogicBasicTransfer" closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="00:15:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="67108864" maxReceivedMessageSize="67108864" messageEncoding="Mtom" textEncoding="utf-8" useDefaultWebProxy="true">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="67108864" maxBytesPerRead="4096" maxNameTableCharCount="67108864" />
      <security mode="None">
        <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
    <binding name="BaseLogicWSHTTP">
      <security mode="None" />
    </binding>
    <binding name="BaseLogicWSHTTPSec" />
  </basicHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="true" />
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
</system.serviceModel>

我不确定这是否会影响流式传输功能,因为我使用的是 WCF4.0 休息模板 哪个配置依赖于 Global.asax。

还有一件事,无论我是否运行服务并传递流,创建的文件总是包含这个东西。

如何删除“NUL”数据?

提前致谢。

编辑

public bool UploadFile(string filename, Stream fileStream)
        {
            try
            {
                FileStream fileToupload = new FileStream(filename, FileMode.Create);
                byte[] bytearray = new byte[10000];
                int bytesRead, totalBytesRead = 0;
                do
                {
                    bytesRead = fileStream.Read(bytearray, totalBytesRead, bytearray.Length - totalBytesRead);
                    totalBytesRead += bytesRead;

                } while (bytesRead > 0);

                fileToupload.Write(bytearray, 0, totalBytesRead);
                fileToupload.Close();
                fileToupload.Dispose();
            }
            catch (Exception ex) { throw new Exception(ex.Message); }
            return true;
        }

【问题讨论】:

    标签: c# wcf rest httpwebresponse


    【解决方案1】:

    我认为您看到空值的原因是以下行。您正在初始化一个缓冲区,但您可能没有填满整个缓冲区:

    fileToupload.Write(bytearray, 0, bytearray.Length);
    fileToupload.Close();
    fileToupload.Dispose();
    

    应该是:

    fileToupload.Write(bytearray, 0, totalBytesRead);
    fileToupload.Close();
    fileToupload.Dispose();
    

    你也总是在每次循环迭代中覆盖你的缓冲区:

    fileStream.Read(bytearray, 0, bytearray.Length)`.  
    

    当你可能想要这个时,它会继续填满你的缓冲区的其余部分:

    fileStream.Read(bytearray, totalBytesRead, byteArray.Length - totalBytesRead);
    

    但是,如果您将写入文件的代码移动到循环内,那么您只需对现有代码进行最少的更改:

    int bytesRead, totalBytesRead = 0;
    do
    {
        bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
        if (bytesRead > 0)
        {
            fileToupload.Write(bytearray, 0, bytesRead);
        }
    } while (bytesRead > 0);
    

    如果您尝试发送比 MaxReceivedMessageSize 更多的数据,您将收到 400。相应调整:

    <binding maxReceivedMessageSize="10485760">
    

    【讨论】:

    • +1 空值已被删除。但是当文件大小达到 1MB 或更大时仍然有错误的请求。你对此有什么想法吗?谢谢
    • @ryan,将maxReceivedMessageSize="10485760" 添加到您在端点中使用的绑定。这将允许您上传最大 10MB 的文件
    • 需要说明的是,您可以上传大于 10MB 的文件,但我上面粘贴的值会将其限制为 10MB
    • 我很抱歉最后一个问题。我上传的文件是 800KB,但它只创建 10KB 的文件,maxReceivedMessageSize="10485760"。这有什么问题?谢谢
    • 嘿@ryan,你使用了我粘贴的服务器代码吗?您最初发布的那个永远不会超过 10KB
    猜你喜欢
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-21
    相关资源
    最近更新 更多