4

I'm using ServiceStack.ServiceClient.Web.XmlServiceClient to connect to a webservice. Is there a way to add an attachment to the request?

More info:

What I am trying to do is avoid using Microsoft.Web.Services2 because I am using Mono. I'm trying to upload an XML datafile, along with an XML request. Just like in this question: Upload report unit via webservice in C# .net to jasperserver

Community
  • 1
  • 1
FlappySocks
  • 3,772
  • 3
  • 32
  • 33

1 Answers1

15

To upload files the best (and fastest) way is to not encode it as a normal request variable but simply upload it to the web service as a normal HTTP Upload with ContentType multipart/form-data, i.e. how HTML forms currently send files to a url.

ServiceStack has built-in support for processing uploaded files this way where a complete example of how to do this in ServiceStack's RestFiles example project.

To upload files using the ServiceClient you can use the .PostFile<T>() method seen in this example:

var fileToUpload = new FileInfo(FilesRootDir + "TESTUPLOAD.txt");

var response = restClient.PostFile<FilesResponse>(WebServiceHostUrl + "files/README.txt",
    fileToUpload, MimeTypes.GetMimeType(fileToUpload.Name));

All uploaded files are made available via the base.RequestContext.Files collection which you can easily process with the SaveTo() method (either as a Stream or a file).

foreach (var uploadedFile in base.RequestContext.Files)
{
    var newFilePath = Path.Combine(targetDir.FullName, uploadedFile.FileName);
    uploadedFile.SaveTo(newFilePath);
}

Similarly related to return a file response (either as an Attachment or directly) you just need to return the FileInfo in a HttpResult like:

return new HttpResult(FileInfo, asAttachment:true);

Multiple File Uploads

You can also use the PostFilesWithRequest APIs available in all .NET Service Clients to upload multiple streams within a single HTTP request. It supports populating Request DTO with any combination of QueryString and POST'ed FormData in addition to multiple file upload data streams, e.g:

using (var stream1 = uploadFile1.OpenRead())
using (var stream2 = uploadFile2.OpenRead())
{
    var client = new JsonServiceClient(baseUrl);
    var response = client.PostFilesWithRequest<MultipleFileUploadResponse>(
        "/multi-fileuploads?CustomerId=123",
        new MultipleFileUpload { CustomerName = "Foo,Bar" },
        new[] {
            new UploadFile("upload1.png", stream1),
            new UploadFile("upload2.png", stream2),
        });
}

Example using only a Typed Request DTO. The JsonHttpClient also includes async equivalents for each of the PostFilesWithRequest APIs:

using (var stream1 = uploadFile1.OpenRead())
using (var stream2 = uploadFile2.OpenRead())
{
    var client = new JsonHttpClient(baseUrl);
    var response = await client.PostFilesWithRequestAsync<MultipleFileUploadResponse>(
        new MultipleFileUpload { CustomerId = 123, CustomerName = "Foo,Bar" },
        new[] {
            new UploadFile("upload1.png", stream1),
            new UploadFile("upload2.png", stream2),
        });
}
mythz
  • 141,670
  • 29
  • 246
  • 390
  • Thank you. I am still a bit unsure how to handle the XML request along with the XML file I have. I have added a little bit more info to my question. – FlappySocks Nov 29 '11 at 00:22
  • Once you get it as a file/stream, you're out of the fx and into your code, i.e. free to do what you want with it? Also it's best to ask a more focused question then extending an existing one towards a non-related path. – mythz Nov 29 '11 at 00:52
  • @mythz: With the [new API](https://github.com/ServiceStack/ServiceStack/wiki/New-Api), is `.PostFile()` still the way to go? – Christian Specht Oct 26 '12 at 11:14
  • Yeah `PostFile` has remained changed. – mythz Oct 26 '12 at 15:33
  • So, is it correct to say that I can currently only upload one file/stream at a time? – flq Apr 02 '13 at 15:15
  • 1
    Warning: Do note that it seems like these inbuilt methods ServiceStack provide for clients to upload files, actually uploads the entire file in memory first. If you have small files, this is fine, but it should generally be avoided. (source: [link](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.HttpClient/JsonHttpClient.cs) line 1053: `var fileBytes = file.Stream.ReadFully();`) – Ykok Apr 15 '19 at 08:52