zoukankan      html  css  js  c++  java
  • RestSharp使用详解(3)OSS文件上传的问题

         基于前文中修改过的RestSharp我们已经可以轻松的调用OSS中大部分API如,GetService (ListBucket),Put Bucket,Get Bucket ACL,Delete Bucket等,接下来就到OSS最重要的操作了——Put Object ,即文件上传。

    1、OSS PUT Object操作不兼容RFC1867文件上传协议

    本以为上传操作会非常简单,根据文档代码我们可以调用以下几个方法添加文件

    IRestRequest AddFile (string name, string path);
    IRestRequest AddFile (string name, byte[] bytes, string fileName);
    IRestRequest AddFile (string name, byte[] bytes, string fileName, string contentType);

    我们第一版的代码就像下面一样了:

            public string PutObjectFromtFile(string bucket, string obj, string filePath)
            {
                var request = new RestRequest();
                request.Resource = "/" + bucket + "/" + obj;
                request.Method = Method.PUT;
                request.AddFile(obj, filePath);
                var response = Execute(request);
                return response.Headers.Where(m => m.Name == "ETag").First().Value.ToString().ToLower().Substring(1, 32);
            }

    进行测试无奈又爆出400错误。我们接着Fiddler抓包,提交数据包结构如下,有部分省略:

    Host: storage.aliyun.com
    Content-Type: multipart/form-data; boundary=---------------------------122872775310383
    Content-Length: 655
    空行
     -----------------------------122872775310383
    Content-Disposition: form-data; name="txt"

         通过查询得知:RestSharp的AddFile操作遵循了RFC1867协议,在上传文件时会添加额外的头文件进行分割。如同我们在浏览器中上传文件时必须在form中设置ENCTYPE必须为multipart/form-data。具体参考:通过解析HTTP协议自己实现文件上传。但是在阿里OSS服务中规定,PUT Object 操作使用PUT方法,并将文件以文件流方式添加到HTTP的body中。

         既然知道了原因我们接下来就进行修改,我们还是先看看Google讨论组上的有没有解决方法,找到一篇有用的帖子PUT's dont honor the RequestFormat ,接下来就对RestSharp大刀阔斧的改造了。

    改造思路如下,首先为添加一个属性,用来标识是否上传原始文件流;然后找到构造multipart协议的代码,根据属性来确定是否上传原始文件。

    我么先找到了添加文件的位置位于Http.cs文件中:

            private void WriteMultipartFormData(Stream requestStream)
            {
                    foreach (var param in Parameters)
                    {
                        WriteStringTo(requestStream, GetMultipartFormData(param));
                    }
    
                    foreach (var file in Files)
                    {
                        // Add just the first part of this param, since we will write the file data directly to the Stream
                        WriteStringTo(requestStream, GetMultipartFileHeader(file));
    
                        // Write the file data directly to the Stream, rather than serializing it to a string.
                        file.Writer(requestStream);
                        WriteStringTo(requestStream, _lineBreak);
                    }
    
                    WriteStringTo(requestStream, GetMultipartFooter());
    }

    我们Http类实现了IHttp接口,我们添加UploadRaw属性在IHttp接口中,并将上面代码改为:

            private void WriteMultipartFormData(Stream requestStream)
            {
                if (!UploadRaw)
                {
                    foreach (var param in Parameters)
                    {
                        WriteStringTo(requestStream, GetMultipartFormData(param));
                    }
                    foreach (var file in Files)
                    {
                        // Add just the first part of this param, since we will write the file data directly to the Stream
                        WriteStringTo(requestStream, GetMultipartFileHeader(file));
    
                        // Write the file data directly to the Stream, rather than serializing it to a string.
                        file.Writer(requestStream);
                        WriteStringTo(requestStream, _lineBreak);
                    }
    
                    WriteStringTo(requestStream, GetMultipartFooter());
                }
                else
                {
                //写入原始文件流
                    var file = Files.First();
                    file.Writer(requestStream);
                }
            }

    初始化Http类的代码在RestClient类中

    private void ConfigureHttp(IRestRequest request, IHttp http)

    代码太多,就不粘贴了,从上面方法中我们的看出来http的属性实际是根据request的值构造的。因此我们还需要在IRestRequest添加一个属性,否则没有办法赋值,同样添加UploadRaw属性。并在ConfigureHttp方法中添加一行 http.UploadRaw=request.UploadRaw即可。
    改造完毕看看我们现在的文件上传方法:

            public string PutObjectFromtFile(string bucket, string obj, string filePath)
            {
                var request = new RestRequest();
                request.Resource = "/" + bucket + "/" + obj;
                request.Method = Method.PUT;
                request.AddFile(obj, filePath);
                //关键在这里
                request.UploadRaw = true;
                var response = Execute(request);
                return response.Headers.Where(m => m.Name == "ETag").First().Value.ToString().ToLower().Substring(1, 32);
            }

    至此,我们OSS API的全部操作都可以顺利的完成了。希望对用到RestSharp的朋友有帮助。

  • 相关阅读:
    Webix快速跨浏览器的JavaScript UI组件
    [转]UltraISO制作U盘启动盘安装Win7/9/10系统攻略
    JavaScript中setTimeout()和setInterval()的区别
    AngularJS中文介绍
    Android Studio参考在线文章
    Android原型界面设计工具
    B-JUI(Best jQuery UI) 前端框架
    Linux Ubuntu download
    Jquery之家5个顶级Material Design框架
    bootstrap绿色大气后台模板下载[转]
  • 原文地址:https://www.cnblogs.com/yanyan45/p/2512262.html
Copyright © 2011-2022 走看看