• 新浪微博SDK开发(2):上传图片的技术难点


    在微博模块中,有一个API是可以发表带一张图片的微博的,当然提交方式是POST。在封装的时候,可能会遇到一个难点——如何上传图片?

    要POST微博的同时带有图片,POST的内容必须为MultiPart form data格式的内容,这个呢,我用到.NET 45中新增的一个相当强大的HttpClient类,位于System.Net.Http命名空间下。这个类的好处在于,它把许多HTTP操作都封装了,让我们使用起来不至于过于痛苦。

    源码下载:http://vdisk.weibo.com/s/z7iFc2gCCwC1b

    无论是GET请求还是POST请求,HttpClient类都允许我们发送一个HttpContent对象,它封装了HTTP内容数据,当然它是一个抽象类,我们用的是它的派生类,请看下图:

     

     StringContent类是把一个字符串发送到服务器,StreamContent类表示数据内容以流的形式收发,FormUrlEncodedContent类封装的数据,说简单一点就是模拟我们在web页上form元素中填写的内容。

    而既有文本又有图片文件的微博,应该使用MultipartFormDataContent来封装,即包含多个段的数据,正因其有多个 Content-Disposition段,我们需要弄一个字符串作为分隔符,在这里,就是把微博正文和图片文件的数据分隔开来,这个字符串常见的形式如“---------------------------a6ecd24f3a2b3cc5”。

    于是,我在SDK中专为POST这种多段数据的HTTP内容写了一个SendRequestWithMultipartFormDataAsync,都是async方法,可以异步等待,这是新特性,有些人不太了解它,其实当你了解后,你会发现await异步等待其实很环保,也节省不少代码。

            internal static async Task<TResult> SendRequestWithMultipartFormDataAsync<TResult>(string relateUrl, IDictionary<string, object> parms, string filename)
            {
                Uri reqUri = new Uri(API_BASE_RUI);
                reqUri = new Uri(reqUri, relateUrl);
                TResult result = default(TResult);
                using (HttpClient client = new HttpClient())
                {
                    string b = "---------------------" + DateTime.Now.Ticks.ToString("x");
                    MultipartFormDataContent formData = new MultipartFormDataContent(b);
                    foreach (var pair in parms)
                    {
                        string str = pair.Value as string;
                        if (str != null)
                        {
                            StringContent stringContent = new StringContent(pair.Value as string);
                            formData.Add(stringContent, pair.Key);
                        }
    
                        Stream stream = pair.Value as Stream;
                        if (stream != null)
                        {
                            StreamContent streamContent = new StreamContent(stream);
                            formData.Add(streamContent, pair.Key, filename);
                        }
                    }
                    var response = await client.PostAsync(reqUri, formData);
                    if (response.IsSuccessStatusCode)
                    {
                        using (Stream backstream = await response.Content.ReadAsStreamAsync())
                        {
                            result = JsonSerializeHelper.ReadDataFromJson<TResult>(backstream);
                        }
                    }
                    else
                    {
                        ErrorData err = null;
                        using (Stream errstream = await response.Content.ReadAsStreamAsync())
                        {
                            err = JsonSerializeHelper.ReadDataFromJson<ErrorData>(errstream);
                        }
                        throw new WeiboException(err);
                    }
                }
    
                return result;
            }

    用于分隔内容的字符串,我是通过把DateTime对象中的Ticks这个数值转为十六进制字符串来实现的,也就是代码中的b变量。

    1、new一个MultipartFormDataContent对象。

    2、微博正文是字符串,所以用StringContent来封装,然后调用MultipartFormDataContent对象的Add方法加进去。

    3、对于图片,我们可以使用流StreamContent,但要注意一个很关键的要素,就是在Add到multipart form data 内容中的时候一定要指定文件名。即调用以下重载:

    public void Add(HttpContent content, string name, string fileName);

    也就是必须为filename参数给予一个文件名,相对路径,绝对路径都无所谓,或者干脆一个文件名(如abc.jpg)都行。就是不能缺了这个参数,否则会上传失败
    将内容添加完毕后,就可以直接调用PostAsync方法向服务器POST数据了,完成后返回HttpResponseMessage类型的实例,它封装了服务器回应的各种消息,可通过IsSuccessStatusCode属性判断服务器是否返回正确的代码(OK,200)。Content属性返回服务器回应的消息正文。

    这样,上传图片的问题就解决了。

  • 相关阅读:
    Oneops运维系统
    采集日志工具fluentbit输出到kafka
    logstash
    Redux学习笔记
    部分浏览器不支持 replaceAll的解决
    windows10系统文件浏览器不显示图片缩略图
    C#项目版本号自定义位置自动向上增加小工具设计与实现
    父类和子类同名的变量和方法决定于哪个
    JdbcTemplate基本使用 增删该差API
    Tomcat结合Web Maven
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/3818337.html
Copyright © 2020-2023  润新知