13

I am trying to send a file to a server over a REST API. The file could potentially be of any type, though it can be limited in size and type to things that can be sent as email attachments.

I think my approach will be to send the file as a binary stream, and then save that back into a file when it arrives at the server. Is there a built in way to do this in .Net or will I need to manually turn the file contents into a data stream and send that?

For clarity, I have control over both the client and server code, so I am not restricted to any particular approach.

Kevin
  • 551
  • 1
  • 9
  • 28
  • What does _"serialize the file to binary"_ mean? All files are in binary already. What _exactly_ are you asking? See [How To Accept a File POST - ASP.Net MVC 4 WebAPI](http://stackoverflow.com/questions/10320232/how-to-accept-a-file-post-asp-net-mvc-4-webapi) for some starting points. – CodeCaster Dec 16 '15 at 18:19
  • You are right, serialization is the wrong way to talk about it, what I meant is do I need to send the binary data stream directly, or use a different tool to send it for me. I've clarified the question and @MutantNinjaCodeMonkey's answer is what I needed – Kevin Dec 16 '15 at 18:24

5 Answers5

8

I'd recommend you look into RestSharp
http://restsharp.org/

The RestSharp library has methods for posting files to a REST service. (RestRequst.AddFile()). I believe on the server-side this will translate into an encoded string into the body, with the content-type in the header specifying the file type.

I've also seen it done by converting a stream to a base-64 string, and transferring that as one of the properties of the serialized json/xml object. Especially if you can set size limits and want to include file meta-data in the request as part of the same object, this works really well.

It really depends how large your files are though. If they are very large, you need to consider streaming, of which the nuances of that is covered in this SO post pretty thoroughly: How do streaming resources fit within the RESTful paradigm?

Community
  • 1
  • 1
1

You could send it as a POST request to the server, passing file as a FormParam.

    @POST
        @Path("/upload")
       //@Consumes(MediaType.MULTIPART_FORM_DATA)
        @Consumes("application/x-www-form-urlencoded")
        public Response uploadFile( @FormParam("uploadFile") String script,  @HeaderParam("X-Auth-Token") String STtoken, @Context HttpHeaders hh) {

            // local variables
            String uploadFilePath = null;
            InputStream fileInputStream = new ByteArrayInputStream(script.getBytes(StandardCharsets.UTF_8));

            //System.out.println(script); //debugging

            try {
                  uploadFilePath = writeToFileServer(fileInputStream, SCRIPT_FILENAME);
            }
            catch(IOException ioe){
               ioe.printStackTrace();
            }
            return Response.ok("File successfully uploaded at " + uploadFilePath + "\n").build();
        }

 private String writeToFileServer(InputStream inputStream, String fileName) throws IOException {

        OutputStream outputStream = null;
        String qualifiedUploadFilePath = SIMULATION_RESULTS_PATH + fileName;

        try {
            outputStream = new FileOutputStream(new File(qualifiedUploadFilePath));
            int read = 0;
            byte[] bytes = new byte[1024];
            while ((read = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
            outputStream.flush();
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
        finally{
            //release resource, if any
            outputStream.close();
        }
        return qualifiedUploadFilePath;
    }
Erick
  • 391
  • 3
  • 6
1

Building on to @MutantNinjaCodeMonkey's suggestion of RestSharp. My use case was posting webform data from jquery's $.ajax method into a web api controller. The restful API service required the uploaded file to be added to the request Body. The default restsharp method of AddFile mentioned above caused an error of The request was aborted: The request was canceled. The following initialization worked:

// Stream comes from web api's HttpPostedFile.InputStream 
     (HttpContext.Current.Request.Files["fileUploadNameFromAjaxData"].InputStream)
using (var ms = new MemoryStream())
{
    fileUploadStream.CopyTo(ms);
    photoBytes = ms.ToArray();
}

var request = new RestRequest(Method.PUT)
{
    AlwaysMultipartFormData = true,
    Files = { FileParameter.Create("file", photoBytes, "file") }
};
Ben Sewards
  • 2,571
  • 2
  • 25
  • 43
1

First, you should login to the server and get an access token.

Next, you should convert your file to stream and post the stream:

private void UploadFile(FileStream stream, string fileName)
{
    string apiUrl = "http://example.com/api";
    var formContent = new MultipartFormDataContent
                {
                    {new StringContent(fileName),"FileName"},
    
                    {new StreamContent(stream),"formFile",fileName},
                };
    using HttpClient httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Add("Authorization", accessToken);
    var response = httpClient.PostAsync(@$"{apiUrl}/FileUpload/save", formContent);
    var result = response.Result.Content.ReadAsStringAsync().Result;
}    

In this example, we upload the file to http://example.com/api/FileUpload/save and the controller has the following method in its FileUpload controller:

[HttpPost("Save")]
public ActionResult Save([FromForm] FileContent fileContent)
{
    // ...
}

public class FileContent
{
    public string FileName { get; set; }
    public IFormFile formFile { get; set; }
}
 
MB_18
  • 1,620
  • 23
  • 37
0
  1. Detect the file/s being transported with the request.
  2. Decide on a path where the file will be uploaded (and make sure CHMOD 777 exists for this directory)
  3. Accept the client connect
  4. Use ready library for the actual upload

Review the following discussion: REST file upload with HttpRequestMessage or Stream?

Community
  • 1
  • 1
Daniel Golub
  • 387
  • 2
  • 6
  • 18
  • I don't know what you mean by number 4. What do you mean by "use ready library"? I will look into that other question, I didn't see that when I was searching for an answer earlier. – Kevin Dec 16 '15 at 18:11
  • There are a couple of ready out-of-the-box libraries for file uploading in .NET A couple of them are: https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.fileupload(v=vs.110).aspx https://www.nuget.org/packages/AjaxUploader/ – Daniel Golub Dec 16 '15 at 18:22