苦苦搞了半个通宵才搞定的直接使用Sliverlight将文件PUT到阿里云OSS

为了公司的项目,小的我各种折腾啊,不过高兴的是实现了Silverlight直接提交至阿里云OSS的文件上传,文件上传再也不用通过服务器中转了。

研究SDK发现还有个Node-oss.js,但还没进行测试。哪天搞一下。成功的话再搞上来。。。

明天还得研究基于ActionScript 2.0/3.0直接上传至阿里云OSS。有得搞了。。。不废话了,把Silverlight上传OSS的代码贴这里,也许大家很多人需要吧。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Net.Browser;
using System.Threading;
using System.Security.Cryptography;
using System.Text;
using SilverlightAliOSSUpload.Common;

namespace SilverlightAliOSSUpload
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }
        byte[] buffer = null;
        string accessKeyId = "Access Key ID";
        string accessKeySecret = "Access Key Secret";
        string fileName = string.Empty;

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            if (dialog.ShowDialog() == true)
            {
                try
                {
                    DateTime dt = DateTime.Now;

                    fileName = dialog.File.Name;

                    WebHeaderCollection collection = new WebHeaderCollection();

                    buffer = new byte[dialog.File.Length];

                    using (Stream stream = dialog.File.OpenRead())
                    {
                        stream.Read(buffer, 0, buffer.Length);
                    }

                    collection[HttpRequestHeader.ContentMd5] = ICryptography.GetMD5(buffer).ToUpper();

                    // PUT\n[Content-MD5]\n\n[GMT Date]\n/[BucketName]/[FileName]
                    HMACSHA1 sha = new HMACSHA1();

                    sha.Key = Encoding.UTF8.GetBytes(accessKeySecret.ToCharArray());

                    // 这里值得说一下,是OSS最丫的垃圾的地方。这里面的签名和URL签名都必须使用Expires时间,也就是要指定过期时间,我这里是10分钟后过期
                    // 就这么一行,调了四个多小时。FUCK
                    byte[] hashBuffer = Encoding.UTF8.GetBytes(string.Format("PUT\n{0}\n\n{1}\n/Bucket/{2}", ICryptography.GetMD5(buffer), Convert.ToInt64(DateTimeToUTC(dt.AddMinutes(10))),
                          fileName).ToCharArray());

                    string hash = Convert.ToBase64String(sha.ComputeHash(hashBuffer));

                    // 因为Silverlight的WebRequest不能创建PUT和DELETE的Method,所以这里只能使用WebRequestCreator来创建
                    HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(
                        new Uri(string.Format("http://Bucket.oss.aliyuncs.com/{0}?OSSAccessKeyId={1}&Expires={2}&Signature={3}", fileName, accessKeyId, Convert.ToInt64(DateTimeToUTC(dt.AddMinutes(10))), hash)));

                    request.Method = "PUT";
                    request.ContentType = "multipart/form-data";
                    request.ContentLength = dialog.File.Length;

                    request.Headers = collection;

                    request.BeginGetRequestStream(new AsyncCallback(AsyncRequestStream), request);


                }
                catch (Exception err)
                {
                    new Thread(() =>
                    {
                        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            label1.Content += err.Message;
                        });
                    }).Start();
                }
            }
        }

        /// <summary>
        /// 转换当前日期至UTC时间格式
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static double DateTimeToUTC(DateTime dt)
        {
            DateTime UnixTimestampLocalZero = System.TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), TimeZoneInfo.Local);
            return (long)(dt - UnixTimestampLocalZero).TotalMilliseconds;
        }

        private void AsyncRequestStream(IAsyncResult ar)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)ar.AsyncState;

                using (Stream stream = request.EndGetRequestStream(ar))
                {
                    stream.Write(buffer, 0, buffer.Length);
                    stream.Flush();
                }

                request.BeginGetResponse(new AsyncCallback(AsyncGetResponse), request);
            }
            catch (Exception err)
            {
                new Thread(() =>
                {
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        label1.Content += err.Message;
                    });
                }).Start();
            }
        }

        private void AsyncGetResponse(IAsyncResult ar)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)ar.AsyncState;

                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(ar);

                using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                {
                    string content = sr.ReadToEnd();
                    new Thread(() =>
                    {
                        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            textBlock1.Text += content;
                        });
                    }).Start();
                }

                response.Close();
            }
            catch (WebException err)
            {
                new Thread(() =>
                {
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        label1.Content = err.Status;

                        using (StreamReader sr = new StreamReader(err.Response.GetResponseStream()))
                        {
                            textBlock1.Text += sr.ReadToEnd();
                        }
                    });
                }).Start();
            }
            catch (Exception err)
            {
                new Thread(() =>
                {
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        label1.Content += err.Message;
                    });
                }).Start();
            }
        }
    }
}

 

posted @ 2014-01-04 01:55  star丶清影  阅读(1397)  评论(13编辑  收藏  举报