Server response / callback after Silverlight file

2019-01-20 12:55发布

问题:

Ok first of all, the unicorn avatars are hilarious. Seriously, I thought my account was compromised. Happy April Fool's day.

Now I'm uploading files via Silverlight to the server. What is the best way to notify Silverlight that the files have been uploaded? Perhaps even toss other information back such as success/failure etc.

I followed a simple tutorial here for my file upload logic

回答1:

First of all re-write the UploadFile function as follows:-

    private void UploadFile(string fileName, Stream data, Action<Exception> callback)
    {
        UriBuilder ub = new UriBuilder("http://localhost:3840/receiver.ashx");
        ub.Query = string.Format("filename={0}", fileName);

        WebClient c = new WebClient();
        c.OpenWriteCompleted += (sender, e) =>
        {
            try
            {
              PushData(data, e.Result);
              e.Result.Close();
              data.Close();  // This blocks until the upload completes
              callback(null);
            }
            catch (Exception er)
            {
              callback(er);
            }
        };
        c.OpenWriteAsync(ub.Uri);
    }

Now you can use this function like this:-

   Stream data = new fi.OpenRead();
   try
   {        
       FileUpload(fi.Name, data, (err) => 
        {
           // Note if you want to fiddle with the UI use dispatcher Invoke here.
           if (err == null)
           {
              // Success
           }
           else
           {
              // Fail do something with the err to disply why
           }
        });

    }
    catch
    {
        data.Dispose();
    }


回答2:

There is a way to upload file and get server response using WebClient in Silverlight.

Internally UploadStringAsync converts string to bytes through its Encoding:

byte[] bytes = this.Encoding.GetBytes(data);

So, I wrote simple base64 encoding wrapper (only actually used methods in my scenario are implemented):

  public class WebClientUploaderBase64Encoding : System.Text.Encoding
  {
    public override int GetMaxCharCount(int byteCount) {throw new NotImplementedException();}

    public override int GetMaxByteCount(int charCount){throw new NotImplementedException();}

    public override int GetCharCount(byte[] bytes, int index, int count){throw new NotImplementedException();}

    public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex){throw new NotImplementedException();}

    public override int GetByteCount(char[] chars, int index, int count)
    {
      var data = System.Convert.FromBase64CharArray(chars, index, count);
      return data.Length;
    }

    public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
    {
      var data = System.Convert.FromBase64CharArray(chars, charIndex, charCount);

      for (int index = 0; index < data.Length; ++index)
        bytes[byteIndex + index] = data[index];
      return data.Length;
    }

    public override string GetString(byte[] bytes, int start, int length)
    {
      return System.Convert.ToBase64String(bytes, start, length);
    }
  }

Now uploading looks like:

private async Task UploadFile(byte[] data)
{
  var client = new WebClient() {Encoding = new WebClientUploaderBase64Encoding()};
  string base64EncodedData = client.Encoding.GetString(data, 0, data.Length);
  var base64EncodedResult = await client.UploadStringTaskAsync("http://api/query", base64EncodedData);
  var resultBytes = client.Encoding.GetBytes(base64EncodedResult);
  var json = Encoding.UTF8.GetString(resultBytes);
}