.NET使用HttpClient以multipart/form-data形式post上傳文件及其相關參數

前言:

  本次要講的是使用.Net HttpClient拼接multipark/form-data形式post上傳文件和相關參數,並接收到上傳文件成功後返回過來的結果(圖片地址,和是否成功)。可能有不少人會說用ajax不是就能夠輕鬆的實現嗎?的確是在不存在跨域問題的前提下使用ajax上傳文件,接收返回結果是最佳的選擇。無奈的是咱們對接的是第三方的一個上傳圖片的接口,並且對方並無對咱們的域名設置容許跨域,爲了可以解決這一問題咱們只可以經過後端請求避免跨域問題。javascript

什麼是multipart/form-data請求:

關於multipart/form-data詳情查看: http://www.javashuo.com/article/p-fiiqzgkp-cu.htmlhtml

Html上傳圖片按鈕:

<div class="cover-hd">
<a href="javascript:;" class="a-uploadCustom">
<input type="file" id="Logoimg" onchange="OnchangeImage(this)" /></a>
</div>

使用ajax將圖片文件流和相關參數傳遞到後端進行拼接:

注意:由於我這裏調用第三方接口須要傳遞(appid應用程序惟一標識,random隨機數,和sign簽名)前端

<script type="text/javascript">
    //後端圖片上傳
    function OnchangeImage(obj) {
        var formData = new FormData();
        var files = $(obj).prop('files'); //獲取到文件列表
        console.log(files[0]);
        formData.append("imgType", 1);
        formData.append("appId","你須要傳遞的參數");
        formData.append("random", "你須要傳遞的參數");
        formData.append("file", files[0]);//圖片文件流
        formData.append("sign", "你須要傳遞的參數");

        console.log(formData);
        jQuery.support.cors = true;
        $.ajax({
            async: true,
            contentType: false, //頭部請求內容格式
            dataType: 'json',
            type: 'post',
            data:formData,
            // 告訴jQuery不要去處理髮送的數據
            processData: false,
            url: "@Url.Action("ImageUpload", "MtVirtualStore")",//後端接收圖片接口
            success: function(data) {
                //後端Httpclient請求成功後返回過來的結果
                console.log(data);
            }
        });
    }
</script>

 

後端接收圖片和參數,並將圖片文件流轉化爲圖片字節類型數據:

//接收前端圖片文件信息
[HttpPost]
public JsonResult ImageUpload(FormContext context)
{
HttpPostedFileBase fileData = Request.Files[0];
string appId=Request["appId"];
string random=Request["random"];
string sign=Request["sign"];
string imgType=Request["imgType"];
if (fileData != null)
{
try{
string fileName = Path.GetFileName(fileData.FileName);//原始文件名稱
byte[] byteFileData = ReadFileBytes(fileData);//文件流轉爲字節流

var resultContext =HttpClientPostUpload(byteFileData,appId,random,sign,imgType, fileName);

return Json(new { code = 1, list = resultContext,msg="上傳成功~"});
}
catch (Exception ex)
{
return Json(new { code = 0, msg = ex.Message });
}
}
else
{
return Json(new { code = 0, msg = "圖片上傳失敗,請稍後再試~" });
}
}
        
//文件流轉化爲字節
/// <summary>
/// 文件流類型轉化字節類型
/// </summary>
/// <param name="fileData">文件流數據</param>
/// <returns></returns>
private byte[] ReadFileBytes(HttpPostedFileBase fileData)
{
byte[] data;
using (Stream inputStream = fileData.InputStream)
{
MemoryStream memoryStream = inputStream as MemoryStream;
if (memoryStream == null)
{
memoryStream = new MemoryStream();
inputStream.CopyTo(memoryStream);
}
data = memoryStream.ToArray();
}
return data;
}

重點,HttpClient拼接multipart/form-data形式參數post提交數據:

/// <summary>
/// 向目標地址提交圖片文件參數數據
/// </summary>
/// <param name="bmpBytes">圖片字節流</param>
/// <param name="appId">appid</param>
/// <param name="random">隨機數</param> 
/// <param name="sign">簽名</param>
/// <param name="imgType">上傳圖片類型</param>     
/// <param name="fileName">圖片名稱</param>
/// <returns></returns>
public string HttpClientPostUpload(byte [] bmpBytes, string appId, string random,,string sign,string imgType,string fileName)
{
using (var client = new HttpClient())
{
List<ByteArrayContent> list = new List<ByteArrayContent>();

var dataContent = new ByteArrayContent(Encoding.UTF8.GetBytes(appId));
dataContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")//內容處置標頭
{
Name = "appId"
};
list.Add(dataContent);

var dataContent2 = new ByteArrayContent(Encoding.UTF8.GetBytes(imgType));
dataContent2.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "imgType"
};
list.Add(dataContent2);

var dataContent3 = new ByteArrayContent(Encoding.UTF8.GetBytes(random));
dataContent3.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "random"
};
list.Add(dataContent3);

var dataContent4 = new ByteArrayContent(Encoding.UTF8.GetBytes(sign));
dataContent4.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "sign"
};
list.Add(dataContent4);
List<ByteArrayContent> list2 = new List<ByteArrayContent>();

var fileContent = new ByteArrayContent(bmpBytes);//填充圖片字節
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name="file",
FileName=fileName
};
list.Add(fileContent);

using (var content =new MultipartFormDataContent())
{
Action<List<ByteArrayContent>> act = (dataContents) =>
{//聲明一個委託,該委託的做用就是將ByteArrayContent集合加入到MultipartFormDataContent中
foreach (var byteArrayContent in dataContents)
{
content.Add(byteArrayContent);
}
};

act(list);//執行act
try
{
var result = client.PostAsync("https://xxxxxx.com/imageUpload/", content).Result;//post請求
return result.Content.ReadAsStringAsync().Result;
}
catch (Exception ex)
{
return ex.Message;
}

}
}
}

使用Fiddler 4 抓包查看請求的參數:

由於咱們沒有辦法看到咱們所拼接成功後的multipark/form-data形式的數據,想要看到對應拼接的請求參數能夠使用 Fiddler 4 抓包工具查看:java

關於Fiddler 4抓包工具的使用能夠閱讀該篇博客:https://www.jianshu.com/p/55f7be58a7e4ajax

抓包獲取到的multipark/form-data形式的請求參數以下圖:json

總結:

  寫到最後才發現,本來只須要一個簡單的請求就能夠解決的問題由於跨域把這個問題變得如此繁瑣,搞得真叫人蛋痛。這裏我試過了不少種方式拼接multipark/form-data形式的請求參數,最後在堅持不懈的嘗試下終於成功了。後端

相關文章
相關標籤/搜索