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的朋友有幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM