简体   繁体   中英

C# Rest API File upload

I am trying too upload a file with C# by an API.

The StreamUtils dont work, I am getting error: "Cannot convert lambda expression to type 'string' because it is not a delegate type".

Any idea on how to upload the file? It is around 100MB.

 public void UploadModel(string ProjectId, string filename, Stream fileStream)
        {

            string access_token_string = Read_Json_Values("access_token");
            string webstring = String.Format("https://api.test.com/v2/projects/{0}/revisions", ProjectId);

            var client = new RestClient(webstring);
            client.Timeout = -1;
            var request = new RestRequest(Method.POST);
            request.AddHeader("Authorization", "Bearer " + access_token_string);
            request.AddHeader("Content-Type", "application/ifc");
            request.AddHeader("xxx-Params", "{\"callbackUri\": \"https://example.com\", \"filename\": \"mk337.ifc\", \"comment\": \"From Postman\", \"model\": \"21312312312312\"}");
            request.AddFile("file", s => StreamUtils.CopyStream(fileStream, s), filename);


            IRestResponse response = client.Execute(request);
            Console.WriteLine("Model is uploaded!");
        }
internal static class StreamUtils
        {
            private const int STREAM_BUFFER_SIZE = 128 * 1024; // 128KB

            public static void CopyStream(Stream source, Stream target)
            { CopyStream(source, target, new byte[STREAM_BUFFER_SIZE]); }

            public static void CopyStream(Stream source, Stream target, byte[] buffer)
            {
                if (source == null) throw new ArgumentNullException("source");
                if (target == null) throw new ArgumentNullException("target");

                if (buffer == null) buffer = new byte[STREAM_BUFFER_SIZE];
                int bufferLength = buffer.Length;
                int bytesRead = 0;
                while ((bytesRead = source.Read(buffer, 0, bufferLength)) > 0)
                    target.Write(buffer, 0, bytesRead);
            }

So you have two issues in your code ...

1. Lambda expression issue

The following line causes the lambda expression issue

request.AddFile("file", s => StreamUtils.CopyStream(fileStream, s), filename);

// This is the function you want to call
void CopyStream(Stream source, Stream target)

So the issue is, that

s => StreamUtils.CopyStream(fileStream, s)

is a Lambda expression, where you define s and give s as second Parameter to

CopyStream(Stream source, Stream target)

but s is not of type Stream. That's why you get the exception.

2. request.AddFile needs Parameters

Assuming you use the RestSharp NuGet package for your REST request (I assume that because the classes look like the once from RestSharp) you should have a look on the different overloads of RestRequest.AddFile():

AddFile(string name, string path, string contentType = null);
AddFile(string name, byte[] bytes, string fileName, string contentType = null);
AddFile(string name, Action<Stream> writer, string fileName, long contentLength, string contentType = null);

All functions need several parameters. I guess you want to use the second definition which is

AddFile(string name, byte[] bytes, string fileName, string contentType = null);

So if we compare it with the line in your code

request.AddFile("file", s => StreamUtils.CopyStream(fileStream, s), filename);

We see that you give following Parameters:

  • "file" as the name
  • Function call (Lambda expression) for the bytes
  • Filename variable for the filename

The first and third parameters look good but second parameter is an issue.

My suggestions:

Define a secound stream parameter in your UploadModel and pass it to the CopyStream function:

public void UploadModel(string ProjectId, string filename, Stream sourceStream, Stream targetStream)
{
    // .... your code still here, just want to show the changing lines
    request.AddFile("file", StreamUtils.CopyStream(sourceStream, targetStream), filename);
}

And if you still want to call StreamUtils.CopyStream() to get the second parameter for request.AddFile, you have to change the function definition as it currently returns void. So instead of:

public static void CopyStream(Stream source, Stream target)
public static void CopyStream(Stream source, Stream target, byte[] buffer)

you have to change it to

public static byte[] CopyStream(Stream source, Stream target)
public static byte[] CopyStream(Stream source, Stream target, byte[] buffer)

which leads us to the changes in the function body itself, as we now have to return a byte[] accordingly to the functions definition (this is just an example and still needs to get the real implementation which I am currently not able to do, just hope that it gives you an impression how to do it):

public static byte[] CopyStream(Stream source, Stream target, byte[] buffer)
{
    // -> Define a byte array
    byte[] bytesToReturn;

    // -> Fill the array with data
    // ...

    // -> return the array
    return bytesToReturn;
}

With these changes it should work.

I think you can convert your input file to Base64 and then send it. See also the answers of other professors what they think.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM