c#multipart/form-data格式 通过HTTP请求上传文件到AliyunOSS

  • 今天接到个需求就是客户端上传文件到Aliyun_oss,因为之前已经使用使用过OSS的sdk 上传过文件本以为是件很容易的事。(本以为。。淦)
  • 这里 我贴上一个Aliyun_oss的介绍网站。里面有阿里云Oss对接的详细说明。https://help.aliyun.com/document_detail/32006.html
  • OK!事情是这样的。我首先去网络上百度了下C#客户端通过上传文件的各种代码,试了好多他一直在报一个错误: MalformedPOSTRequest
  • 服务层直接返回400
  • 错误消息:The body of your POST request is not well-formed multipart/form-data.
    错误原因:PostObject请求中表单域格式不符合要求。
    解决方案:遵循表单域格式要求
    然后就到Aliyun_OSS错误码对照哪里找相关的错误解决方案
    在这里插入图片描述
    以上是老马给出的解释。细心的我发现了马哥给提供了个c#demo
    在这里插入图片描述
    OK!看demo,上demo
                var boundary = "9431149156168";
                var webRequest = (HttpWebRequest)WebRequest.Create(requestUri);
                webRequest.Timeout = -1;
                webRequest.Method = "POST";
                webRequest.ContentType = "multipart/form-data; boundary=" + boundary;

                var objectName = "xxx";
                var signature = ComputeSignature(accessKeySecret, encPolicy);

                var fileContent = "这是一行简单的测试文本";
                var requestBody = "--" + boundary + "\r\n" 
                        + "Content-Disposition: form-data; name=\"key\"\r\n"
                        + "\r\n" + "user/eric/${filename}" + "\r\n"
                        + "--" + boundary + "\r\n"
                        + "Content-Disposition: form-data; name=\"bucket\"\r\n"
                        + "\r\n" + bucketName + "\r\n"
                        + "--" + boundary + "\r\n"
                        + "Content-Disposition: form-data; name=\"x-oss-meta-tag\"\r\n"
                        + "\r\n" + "dummy_etag_xxx" + "\r\n"
                        + "--" + boundary + "\r\n"
                        + "Content-Disposition: form-data; name=\"OSSAccessKeyId\"\r\n"
                        + "\r\n" + accessKeyId + "\r\n"
                        + "--" + boundary + "\r\n"
                        + "Content-Disposition: form-data; name=\"policy\"\r\n"
                        + "\r\n" + encPolicy + "\r\n"
                        + "--" + boundary + "\r\n"
                        + "Content-Disposition: form-data; name=\"Signature\"\r\n"
                        + "\r\n" + signature + "\r\n"
                        + "--" + boundary + "\r\n"
                        + "Content-Disposition: form-data; name=\"file\"; filename=\"" + objectName + "\"\r\n\r\n" 
                        + fileContent + "\r\n" 
                        + "--" + boundary + "\r\n" 
                        + "Content-Disposition: form-data; name=\"submit\"\r\n\r\nUpload to OSS\r\n" 
                        + "--" + boundary + "--\r\n";

                webRequest.ContentLength = requestBody.Length;
                using (var ms = new MemoryStream())
                {
                    var writer = new StreamWriter(ms, new UTF8Encoding());
                    try
                    {
                        writer.Write(requestBody);
                        writer.Flush();
                        ms.Seek(0, SeekOrigin.Begin);

                        webRequest.ContentLength = ms.Length;
                        using (var requestStream = webRequest.GetRequestStream())
                        {
                            ms.WriteTo(requestStream);
                        }
                    }
                    finally
                    {
                        writer.Dispose();
                    }
                }

                var response = webRequest.GetResponse() as HttpWebResponse;
                if (response.StatusCode == HttpStatusCode.NoContent)
                {
                    Console.WriteLine("Post object succeed!");
                }

以上是马哥给提供的demo实例。但是这demo。没有具体上传文件的模块。他的文件就是这一句话,当时内心就EMO…在这里插入图片描述
然后就开始参考网上的代码,看看他们是怎么传输文件的。但是还是一直报
MalformedPOSTRequest 。。400错误。很长时间都没有找到原因。然后我就只能找下场外求助了。在这里我要特别感谢下我的Friend(小海)。
这些都要仔细排查,如果你们也遇到了我这样的问题。
在这里插入图片描述
好了,我也贴一下我的代码

        /// <summary>
        /// 请求上传图片到阿里云
        /// </summary>
        /// <param name="url">上传地址</param>
        /// <param name="filepath">本地文件路径</param>
        /// <param name="dic">上传的数据信息</param>
        /// <returns></returns>
        public static bool UploadFilesToRemoteUrl(string url, string filepath, Dictionary<string, string> dic)
        {
            try
            {
                string boundary = DateTime.Now.Ticks.ToString("x");

                byte[] boundarybytes = System.Text.Encoding.UTF8.GetBytes("--" + boundary + "\r\n");

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

                request.Method = "POST";

                request.ContentType = "multipart/form-data; boundary=" + boundary;

                Stream rs = request.GetRequestStream();

                var endBoundaryBytes = System.Text.Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");

                string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n" + "\r\n" + "{1}" + "\r\n";
                if (dic != null)
                {
                    foreach (string key in dic.Keys)
                    {
                        rs.Write(boundarybytes, 0, boundarybytes.Length);

                        string formitem = string.Format(formdataTemplate, key, dic[key]);

                        byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);

                        rs.Write(formitembytes, 0, formitembytes.Length);
                    }
                }

                string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n\r\n";
                {
                    rs.Write(boundarybytes, 0, boundarybytes.Length);

                    var header = string.Format(headerTemplate, "file", Path.GetFileName(filepath));

                    var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);

                    rs.Write(headerbytes, 0, headerbytes.Length);

                    using (var fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read))
                    {
                        var buffer = new byte[1024];

                        var bytesRead = 0;

                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                        {
                            rs.Write(buffer, 0, bytesRead);
                        }
                    }
                    var cr = Encoding.UTF8.GetBytes("\r\n");

                    rs.Write(cr, 0, cr.Length);
                }

                rs.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);

                var response = request.GetResponse() as HttpWebResponse;

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    return true;
                }
            }
            catch (Exception e)
            {
                LogHelper.Error("文件上传Aliyun异常,淦", e);
            }
            return false;
        }

别问我为什么写完文件还要加个换行符,问的话你就去掉试试(试试就试试emo…)
加油西红柿!!!


版权声明:本文为qq_36222985原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。