1.第三方提供了這麼一個API接口,POST後將附件以file文件上傳,通過postman工具界面是下面這種樣子
Body爲form-data類型,不管是文本還是文件,都能在value上填上去
2.C#實現接口調用代碼
public static string PostForm(string url, List<FormItemModel> formItems, CookieContainer cookieContainer = null, string refererUrl = null, Encoding encoding = null, int timeOut = 20000)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
#region 初始化請求對象
request.Method = "POST";
request.Timeout = timeOut;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
request.KeepAlive = true;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
if (!string.IsNullOrEmpty(refererUrl))
request.Referer = refererUrl;
if (cookieContainer != null)
request.CookieContainer = cookieContainer;
#endregion
string boundary = "----" + DateTime.Now.Ticks.ToString("x");//分隔符
request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
//請求流
var postStream = new MemoryStream();
#region 處理Form表單請求內容
//是否用Form上傳文件
var formUploadFile = formItems != null && formItems.Count > 0;
if (formUploadFile)
{
//文件數據模板
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 dataFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}";
foreach (var item in formItems)
{
string formdata = null;
if (item.IsFile)
{
//上傳文件
formdata = string.Format(
fileFormdataTemplate,
item.Key, //表單鍵
item.FileName);
}
else
{
//上傳文本
formdata = string.Format(
dataFormdataTemplate,
item.Key,
item.Value);
}
//統一處理
byte[] formdataBytes = null;
//第一行不需要換行
if (postStream.Length == 0)
formdataBytes = Encoding.UTF8.GetBytes(formdata.Substring(2, formdata.Length - 2));
else
formdataBytes = Encoding.UTF8.GetBytes(formdata);
postStream.Write(formdataBytes, 0, formdataBytes.Length);
//寫入文件內容
if (item.FileContent != null && item.FileContent.Length > 0)
{
using (var stream = item.FileContent)
{
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
postStream.Write(buffer, 0, bytesRead);
}
}
}
}
//結尾
var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
postStream.Write(footer, 0, footer.Length);
}
else
{
request.ContentType = "application/x-www-form-urlencoded";
}
#endregion
request.ContentLength = postStream.Length;
#region 輸入二進制流
if (postStream != null)
{
postStream.Position = 0;
//直接寫入流
Stream requestStream = request.GetRequestStream();
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
}
////debug
//postStream.Seek(0, SeekOrigin.Begin);
//StreamReader sr = new StreamReader(postStream);
//var postStr = sr.ReadToEnd();
postStream.Close();//關閉文件訪問
}
#endregion
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (cookieContainer != null)
{
response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
}
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.UTF8))
{
string retString = myStreamReader.ReadToEnd();
return retString;
}
}
}
public class FormItemModel
{
/// <summary>
/// 表單鍵,request["key"]
/// </summary>
public string Key { set; get; }
/// <summary>
/// 表單值,上傳文件時忽略,request["key"].value
/// </summary>
public string Value { set; get; }
/// <summary>
/// 是否是文件
/// </summary>
public bool IsFile
{
get
{
if (FileContent == null || FileContent.Length == 0)
return false;
if (FileContent != null && FileContent.Length > 0 && string.IsNullOrWhiteSpace(FileName))
throw new Exception("上傳文件時 FileName 屬性值不能爲空");
return true;
}
}
/// <summary>
/// 上傳的文件名
/// </summary>
public string FileName { set; get; }
/// <summary>
/// 上傳的文件內容
/// </summary>
public Stream FileContent { set; get; }
}
模擬post調用
var url = "http://127.0.0.1/testformdata.aspx?aa=1&bb=2&ccc=3";
var log1=@"D:\temp\log1.txt";
var log2 = @"D:\temp\log2.txt";
var formDatas = new List<Grass.Net.FormItemModel>();
//添加文件
formDatas.Add(new Grass.Net.FormItemModel()
{
Key="log1",
Value="",
FileName = "log1.txt",
FileContent=File.OpenRead(log1)
});
formDatas.Add(new Grass.Net.FormItemModel()
{
Key = "log2",
Value = "",
FileName = "log2.txt",
FileContent = File.OpenRead(log2)
});
//添加文本
formDatas.Add(new Grass.Net.FormItemModel()
{
Key = "id",
Value = "id-test-id-test-id-test-id-test-id-test-"
});
formDatas.Add(new Grass.Net.FormItemModel()
{
Key = "name",
Value = "name-test-name-test-name-test-name-test-name-test-"
});
//提交表單
var result = PostForm(url, formDatas);
至此引用別人的資料:https://www.cnblogs.com/xiaosuxing/p/13403172.html
3.以上方法讀流是通過文件存取的絕對路徑去轉換爲流,進而去請求第三方接口把文件以流的方式上傳
如果是文件服務器上的URL,則此方法不能通用,也試過將流轉換都不行,最後找到一種思路可行,先將URL下載存到臨時文件夾裏,再通過以上方法將文件讀取成流後上傳,代碼如下
/// <summary>
/// 根據文件服務器上的地址URL保存文件到臨時路徑
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static Stream HttpDownload(string url)
{
using (var client = new WebClient())
{
string tempFile = Path.GetTempFileName();
client.DownloadFile(url, tempFile);//下載臨時文件
return FileToStream(tempFile, true);//轉文件流後刪除臨時文件夾
}
}
/// <summary>
/// 文件轉流
/// </summary>
/// <param name="fileName">文件路徑</param>
/// <param name="isDelete">是否刪除臨時文件</param>
/// <returns></returns>
public static Stream FileToStream(string fileName, bool isDelete = false)
{
//打開文件
FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
// 讀取文件的 byte[]
byte[] bytes = new byte[fileStream.Length];
fileStream.Read(bytes, 0, bytes.Length);
fileStream.Close();
// 把 byte[] 轉換成 Stream
Stream stream = new MemoryStream(bytes);
if (isDelete)
{
File.Delete(fileName);//刪除臨時文件
}
return stream;
}