官方提供的接口说明和示例是基于java的,却没有对具体的header作出更详细的说明,导致很难使用C#语言转换,几经测试,总算找到了个不是太完整的解决方法,代码如下。
///
///POST文件
///
///
///
/// 比如钉钉上传媒体文件使用的是media,该值用于服务端接收到数据时读取该keyname之后相关的数据。
/// 文件数据
/// 文件名
///
public static string Post(string url,
string fileKeyName,
byte[] fileBuffer,
String fileName,
int timeout)
{
var boundary = SecurityHelper.GenerateRadomStr();
WebClient webClient = new WebClient();
webClient.Headers.Add("Content-Type", string.Format("multipart/form-data; boundary={0}", boundary));
string fileFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition:form-data;name=\"{0}\";filename=\"{1}\"" +
"\r\nContent-Type:application/octet-stream" +
"\r\n\r\n";
string formDataHeader = String.Format(fileFormdataTemplate, "media", fileName);
byte[] formDataHeaderBuffer = Encoding.UTF8.GetBytes(formDataHeader);
string begin = $"--{boundary}\r\n";
byte[] beginBuffer = Encoding.UTF8.GetBytes(begin);
string end = $"\r\n--{boundary}--\r\n";
byte[] endBuffer = Encoding.UTF8.GetBytes(end); ;
byte[] dataStream = new byte[formDataHeaderBuffer.Length + beginBuffer.Length + fileBuffer.Length + endBuffer.Length];
formDataHeaderBuffer.CopyTo(dataStream, 0);
beginBuffer.CopyTo(dataStream, formDataHeaderBuffer.Length);
fileBuffer.CopyTo(dataStream, formDataHeaderBuffer.Length + begin.Length);
endBuffer.CopyTo(dataStream, formDataHeaderBuffer.Length + begin.Length + fileBuffer.Length);
var returnBuffer = webClient.UploadData(url, "POST", dataStream);
Encoding encode = Encoding.UTF8;
string resultJson = encode.GetString(returnBuffer);
return resultJson;
}
调用的代码
int timeout = 1000 * 60 * 5;
String resultJson = RequestHelper.Post(requestUrl, "media", fileBuffer, fileName, timeout);//media是固定的字符串
其中fileBuffer为文件的字节流,requestUrl按照接口的方式找接而成https://oapi.dingtalk.com/media/upload?access_token=ACCESS_TOKEN&type=TYPE。
在上传成功后,需要再下载下来,下载时,由于成功和失败的返回数据不一样,所以需要先对前面的若干字节进行了试探处理,之后再依据试探结果继续处理,代码如下
附上读取媒体文件的方法
#region FetchMediaFile Function
///
/// 获取媒体文件
///
/// 媒体文件的id
///
public static DDMediaFetchResult FetchMediaFile(string mediaId)
{
DDMediaFetchResult result = null;
string apiurl = FormatApiUrlWithToken(Urls.media_get);
apiurl = $"{apiurl}&{Keys.media_id}={mediaId}";
WebClient webClient = new WebClient();
var data = webClient.DownloadData(apiurl);
int testHeaderMaxLength = 100;
var testHeaderBuffer = new byte[(data.Length < testHeaderMaxLength ? data.Length : testHeaderMaxLength)];
Array.Copy(data, 0, testHeaderBuffer, 0, testHeaderBuffer.Length);
Encoding encoder = Encoding.UTF8;
String testHeaderStr = encoder.GetString(testHeaderBuffer);
if (testHeaderStr.StartsWith("--"))
{//正常返回数据时,第一行数据为分界线,而分界线必然以"--"开始.
var tempArr = testHeaderStr.Split(new String[] { Environment.NewLine }, StringSplitOptions.None);
string boundary = tempArr[0] + Environment.NewLine;
int boundaryByteLength = encoder.GetBytes(boundary).Length;
byte[] destData = new byte[data.Length-boundaryByteLength];
Array.Copy(data, boundaryByteLength, destData, 0, destData.Length);
result = new DDMediaFetchResult();
result.ErrCode = DDErrCodeEnum.OK;
result.ErrMsg = "OK";
result.Data = destData;
const string Content_Length = "Content-Length";
if (webClient.ResponseHeaders == null || (!webClient.ResponseHeaders.AllKeys.Contains(Content_Length)))
{
result.FileLength = -1;
}
var lengthStr = webClient.ResponseHeaders[Content_Length];
int length = 0;
if (int.TryParse(lengthStr, out length))
{
result.FileLength = length;
}
else
{
result.FileLength = 0;
}
const string Content_Type = "Content-Type";
if (webClient.ResponseHeaders == null || (!webClient.ResponseHeaders.AllKeys.Contains(Content_Type)))
{
result.FileType = "unknown";
}
else
{
result.FileType = webClient.ResponseHeaders[Content_Type];
}
}
else
{
string resultJson = encoder.GetString(data);
result = DDRequestAnalyzer.AnalyzeResult(resultJson);//将resultJson反序化为DDMediaFetchResult
}
return result;
}
#endregion
///
/// 媒体文件获取结果
///
public class DDMediaFetchResult
{
///
/// 错误码
///
public int ErrCode{get;set;
///
/// 错误消息
///
public string ErrMsg { get; set; }}
///
/// HTTP响应头
///
public Dictionary Header { get; set; }
///
/// 获取的数据
///
public byte[] Data { get; set; }
///
/// 文件长度
///
public int FileLength { get; set; }
///
/// 文件类型
///
public String FileType { get; set; }
}
将收到的数据存成文件即可,比如将前面上传得到的mediaid传入后,下载得到了下面的图
附生成随机串的方法
#region GenerateRadomStr
///
/// 生成随机字符串
///
/// 随机串的长度
///
public static string GenerateRadomStr(int length = 16)
{
string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
string str = "";
Random rad = new Random();
for (int i = 0; i < length; i++)
{
str += chars.Substring(rad.Next(0, chars.Length - 1), 1);
}
return str;
}
#endregion
转载请注明出处。