C# Rest API 文件上传
Posted
技术标签:
【中文标题】C# Rest API 文件上传【英文标题】:C# Rest API File upload 【发布时间】:2020-05-30 07:31:33 【问题描述】:我也在尝试通过 API 使用 C# 上传文件。
StreamUtils 不起作用,我收到错误消息:“无法将 lambda 表达式转换为类型‘字符串’,因为它不是委托类型”。
知道如何上传文件吗? 大约 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);
【问题讨论】:
我可以假设这一行request.AddFile("file",s=>StreamUtils.CopyStream(fileStream, s), filename);
抛出异常,但需要澄清。
行 request.AddFile("file", s => StreamUtils.CopyStream(fileStream, s), filename) 导致问题,因为 "s => StreamUtils.CopyStream(fileStream, s)"是一个 lambda 表达式,而不是一个流。您要做的就是在函数 StreamUtils.CopyStream(Stream source, Stream target) 中按预期定义一个目标 Stream
您对request.AddFile()
的调用似乎与任何可用的方法签名都不匹配:see this link for clarification。
这有帮助吗?它提供了如何使用 RestSharp ***.com/questions/32876606/… 上传文件的答案
@rekcul 嘿,你能提供一个示例代码吗?
【参考方案1】:
所以您的代码中有两个问题 ...
1. Lambda 表达式问题
以下行导致 lambda 表达式问题
request.AddFile("file", s => StreamUtils.CopyStream(fileStream, s), filename);
// This is the function you want to call
void CopyStream(Stream source, Stream target)
所以问题是,
s => StreamUtils.CopyStream(fileStream, s)
是一个 Lambda 表达式,您可以在其中定义 s 并将 s 作为第二个参数提供给
CopyStream(Stream source, Stream target)
但 s 不是 Stream 类型。这就是你得到异常的原因。
2。 request.AddFile 需要参数
假设您对 REST 请求使用 RestSharp NuGet 包(我假设因为这些类看起来像来自 RestSharp 的一次),您应该看看 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);
所有函数都需要几个参数。我猜你想使用第二个定义,即
AddFile(string name, byte[] bytes, string fileName, string contentType = null);
因此,如果我们将其与您的代码中的行进行比较
request.AddFile("file", s => StreamUtils.CopyStream(fileStream, s), filename);
我们看到您提供了以下参数:
“文件”作为名称 字节的函数调用(Lambda 表达式) 文件名的文件名变量第一个和第三个参数看起来不错,但第二个参数是个问题。
我的建议:
在您的 UploadModel 中定义第二个流参数并将其传递给 CopyStream 函数:
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);
如果您仍想调用 StreamUtils.CopyStream() 来获取 request.AddFile 的第二个参数,则必须更改函数定义,因为它当前返回 void。所以而不是:
public static void CopyStream(Stream source, Stream target)
public static void CopyStream(Stream source, Stream target, byte[] buffer)
你必须把它改成
public static byte[] CopyStream(Stream source, Stream target)
public static byte[] CopyStream(Stream source, Stream target, byte[] buffer)
这导致我们改变了函数体本身,因为我们现在必须根据函数定义返回一个字节[](这只是一个例子,仍然需要获得我目前无法实现的真正实现要做,只是希望它给你一个印象如何去做):
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;
通过这些更改,它应该可以工作。
【讨论】:
【参考方案2】:我认为您可以将输入文件转换为 Base64,然后发送。 另见其他教授的回答他们的想法。
【讨论】:
以上是关于C# Rest API 文件上传的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 中正确使用 WCF REST API 上的 Stream 将文件(图像/视频/等)上传到服务器?
通过 REST API 上传多部分文件会损坏文件并增加文件大小