如何使用 HTTP POST 多部分/表单数据将文件上传到服务器?

我正在开发 Windows Phone 8应用程序。我想通过 PHP Web 服务上传 SQLite 数据库,使用 HTTP POST 请求和 MIME 类型的 multipart/form-data 以及一个名为“ userid = SOME _ ID”的字符串数据。

我不想使用第三方库,如 HttpClient,RestSharp 或 MyToolkit。我尝试下面的代码,但它没有上传文件 & 也没有给我任何错误。它在 Android、 PHP 等系统中运行良好,所以在 Web 服务中没有问题。下面是我给出的代码(WP8)。怎么了?

我谷歌过了,不知道 WP8的具体情况

async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(DBNAME);
//Below line gives me file with 0 bytes, why? Should I use
//IsolatedStorageFile instead of StorageFile
//var file = await ApplicationData.Current.LocalFolder.GetFileAsync(DBNAME);
byte[] fileBytes = null;
using (var stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}


//var res = await HttpPost(Util.UPLOAD_BACKUP, fileBytes);
HttpPost(fileBytes);
}


private void HttpPost(byte[] file_bytes)
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.myserver.com/upload.php");
httpWebRequest.ContentType = "multipart/form-data";
httpWebRequest.Method = "POST";
var asyncResult = httpWebRequest.BeginGetRequestStream((ar) => { GetRequestStreamCallback(ar, file_bytes); }, httpWebRequest);
}


private void GetRequestStreamCallback(IAsyncResult asynchronousResult, byte[] postData)
{
//DON'T KNOW HOW TO PASS "userid=some_user_id"
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
Stream postStream = request.EndGetRequestStream(asynchronousResult);
postStream.Write(postData, 0, postData.Length);
postStream.Close();
var asyncResult = request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}


private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
streamResponse.Close();
streamRead.Close();
response.Close();
}

我也试图在 Windows8中解决我的问题,但它也不起作用。

public async Task Upload(byte[] fileBytes)
{
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture)))
{
content.Add(new StreamContent(new MemoryStream(fileBytes)));
//Not sure below line is true or not
content.Add(new StringContent("userid=farhanW8"));
using (var message = await client.PostAsync("http://www.myserver.com/upload.php", content))
{
var input = await message.Content.ReadAsStringAsync();
}
}
}
}
409347 次浏览

使用 MultipartFormDataContent 的基本实现:-

HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();


form.Add(new StringContent(username), "username");
form.Add(new StringContent(useremail), "email");
form.Add(new StringContent(password), "password");
form.Add(new ByteArrayContent(file_bytes, 0, file_bytes.Length), "profile_pic", "hello1.jpg");
HttpResponseMessage response = await httpClient.PostAsync("PostUrl", form);


response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;

这是我最后的工作代码。我的 Web 服务需要一个文件(POST 参数名是“ file”)和一个字符串值(POST 参数名是“ userid”)。

/// <summary>
/// Occurs when upload backup application bar button is clicked. Author : Farhan Ghumra
/// </summary>
private async void btnUploadBackup_Click(object sender, EventArgs e)
{
var dbFile = await ApplicationData.Current.LocalFolder.GetFileAsync(Util.DBNAME);
var fileBytes = await GetBytesAsync(dbFile);
var Params = new Dictionary<string, string> { { "userid", "9" } };
UploadFilesToServer(new Uri(Util.UPLOAD_BACKUP), Params, Path.GetFileName(dbFile.Path), "application/octet-stream", fileBytes);
}


/// <summary>
/// Creates HTTP POST request & uploads database to server. Author : Farhan Ghumra
/// </summary>
private void UploadFilesToServer(Uri uri, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData)
{
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest.Method = "POST";
httpWebRequest.BeginGetRequestStream((result) =>
{
try
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (Stream requestStream = request.EndGetRequestStream(result))
{
WriteMultipartForm(requestStream, boundary, data, fileName, fileContentType, fileData);
}
request.BeginGetResponse(a =>
{
try
{
var response = request.EndGetResponse(a);
var responseStream = response.GetResponseStream();
using (var sr = new StreamReader(responseStream))
{
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
string responseString = streamReader.ReadToEnd();
//responseString is depend upon your web service.
if (responseString == "Success")
{
MessageBox.Show("Backup stored successfully on server.");
}
else
{
MessageBox.Show("Error occurred while uploading backup on server.");
}
}
}
}
catch (Exception)
{


}
}, null);
}
catch (Exception)
{


}
}, httpWebRequest);
}


/// <summary>
/// Writes multi part HTTP POST request. Author : Farhan Ghumra
/// </summary>
private void WriteMultipartForm(Stream s, string boundary, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData)
{
/// The first boundary
byte[] boundarybytes = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
/// the last boundary.
byte[] trailer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
/// the form data, properly formatted
string formdataTemplate = "Content-Dis-data; name=\"{0}\"\r\n\r\n{1}";
/// the form-data file upload, properly formatted
string fileheaderTemplate = "Content-Dis-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n";


/// Added to track if we need a CRLF or not.
bool bNeedsCRLF = false;


if (data != null)
{
foreach (string key in data.Keys)
{
/// if we need to drop a CRLF, do that.
if (bNeedsCRLF)
WriteToStream(s, "\r\n");


/// Write the boundary.
WriteToStream(s, boundarybytes);


/// Write the key.
WriteToStream(s, string.Format(formdataTemplate, key, data[key]));
bNeedsCRLF = true;
}
}


/// If we don't have keys, we don't need a crlf.
if (bNeedsCRLF)
WriteToStream(s, "\r\n");


WriteToStream(s, boundarybytes);
WriteToStream(s, string.Format(fileheaderTemplate, "file", fileName, fileContentType));
/// Write the file data to the stream.
WriteToStream(s, fileData);
WriteToStream(s, trailer);
}


/// <summary>
/// Writes string to stream. Author : Farhan Ghumra
/// </summary>
private void WriteToStream(Stream s, string txt)
{
byte[] bytes = Encoding.UTF8.GetBytes(txt);
s.Write(bytes, 0, bytes.Length);
}


/// <summary>
/// Writes byte array to stream. Author : Farhan Ghumra
/// </summary>
private void WriteToStream(Stream s, byte[] bytes)
{
s.Write(bytes, 0, bytes.Length);
}


/// <summary>
/// Returns byte array from StorageFile. Author : Farhan Ghumra
/// </summary>
private async Task<byte[]> GetBytesAsync(StorageFile file)
{
byte[] fileBytes = null;
using (var stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}


return fileBytes;
}

我非常感谢 达林 · 卢梭对我的帮助。

你可以使用这个类:

using System.Collections.Specialized;
class Post_File
{
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
byte[] boundarybytesF = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n");  // the first time it itereates, you need to make sure it doesn't put too many new paragraphs down or it completely messes up poor webbrick.




HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
wr.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
var nvc2 = new NameValueCollection();
nvc2.Add("Accepts-Language", "en-us,en;q=0.5");
wr.Headers.Add(nvc2);
wr.ContentType = "multipart/form-data; boundary=" + boundary;




Stream rs = wr.GetRequestStream();


bool firstLoop = true;
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
if (firstLoop)
{
rs.Write(boundarybytesF, 0, boundarybytesF.Length);
firstLoop = false;
}
else
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
}
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);


string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, new FileInfo(file).Name, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);


FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();


byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();


WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
}
catch (Exception ex)
{
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
}

使用它:

NameValueCollection nvc = new NameValueCollection();
//nvc.Add("id", "TTR");
nvc.Add("table_name", "uploadfile");
nvc.Add("commit", "uploadfile");
Post_File.HttpUploadFile("http://example/upload_file.php", @"C:\user\yourfile.docx", "uploadfile", "application/vnd.ms-excel", nvc);

示例服务器 upload_file.php:

m('File upload '.(@copy($_FILES['uploadfile']['tmp_name'],getcwd().'\\'.'/'.$_FILES['uploadfile']['name']) ? 'success' : 'failed'));
function m($msg) {
echo '<div style="background:#f1f1f1;border:1px solid #ddd;padding:15px;font:14px;text-align:center;font-weight:bold;">';
echo $msg;
echo '</div>';
}

我已经玩了一会儿,想出了一个简化的、更通用的解决方案:

private static string sendHttpRequest(string url, NameValueCollection values, NameValueCollection files = null)
{
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
// The first boundary
byte[] boundaryBytes = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
// The last boundary
byte[] trailer = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
// The first time it itereates, we need to make sure it doesn't put too many new paragraphs down or it completely messes up poor webbrick
byte[] boundaryBytesF = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n");


// Create the request and set parameters
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = "POST";
request.KeepAlive = true;
request.Credentials = System.Net.CredentialCache.DefaultCredentials;


// Get request stream
Stream requestStream = request.GetRequestStream();


foreach (string key in values.Keys)
{
// Write item to stream
byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}", key, values[key]));
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
requestStream.Write(formItemBytes, 0, formItemBytes.Length);
}


if (files != null)
{
foreach(string key in files.Keys)
{
if(File.Exists(files[key]))
{
int bytesRead = 0;
byte[] buffer = new byte[2048];
byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", key, files[key]));
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
requestStream.Write(formItemBytes, 0, formItemBytes.Length);


using (FileStream fileStream = new FileStream(files[key], FileMode.Open, FileAccess.Read))
{
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
// Write file content to stream, byte by byte
requestStream.Write(buffer, 0, bytesRead);
}


fileStream.Close();
}
}
}
}


// Write trailer and close stream
requestStream.Write(trailer, 0, trailer.Length);
requestStream.Close();


using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream()))
{
return reader.ReadToEnd();
};
}

You can use it like this:

string fileLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "somefile.jpg";
NameValueCollection values = new NameValueCollection();
NameValueCollection files = new NameValueCollection();
values.Add("firstName", "Alan");
files.Add("profilePicture", fileLocation);
sendHttpRequest("http://example.com/handler.php", values, files);

在 PHP 脚本中,您可以像这样处理数据:

echo $_POST['firstName'];
$name = $_POST['firstName'];
$image = $_FILES['profilePicture'];
$ds = DIRECTORY_SEPARATOR;
move_uploaded_file($image['tmp_name'], realpath(dirname(__FILE__)) . $ds . "uploads" . $ds . $image['name']);

This simplistic version also works.

public void UploadMultipart(byte[] file, string filename, string contentType, string url)
{
var webClient = new WebClient();
string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
webClient.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
var fileData = webClient.Encoding.GetString(file);
var package = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n{3}\r\n--{0}--\r\n", boundary, filename, contentType, fileData);


var nfile = webClient.Encoding.GetBytes(package);


byte[] resp = webClient.UploadData(url, "POST", nfile);
}

如果需要,添加任何额外的必需标头。

它适用于视窗电话8.1。你可以试试这个。

Dictionary<string, object> _headerContents = new Dictionary<string, object>();
const String _lineEnd = "\r\n";
const String _twoHyphens = "--";
const String _boundary = "*****";
private async void UploadFile_OnTap(object sender, System.Windows.Input.GestureEventArgs e)
{
Uri serverUri = new Uri("http:www.myserver.com/Mp4UploadHandler", UriKind.Absolute);
string fileContentType = "multipart/form-data";
byte[] _boundarybytes = Encoding.UTF8.GetBytes(_twoHyphens + _boundary + _lineEnd);
byte[] _trailerbytes = Encoding.UTF8.GetBytes(_twoHyphens + _boundary + _twoHyphens + _lineEnd);
Dictionary<string, object> _headerContents = new Dictionary<string, object>();
SetEndHeaders();  // to add some extra parameter if you need


httpWebRequest = (HttpWebRequest)WebRequest.Create(serverUri);
httpWebRequest.ContentType = fileContentType + "; boundary=" + _boundary;
httpWebRequest.Method = "POST";
httpWebRequest.AllowWriteStreamBuffering = false;  // get response after upload header part


var fileName = Path.GetFileName(MediaStorageFile.Path);
Stream fStream = (await MediaStorageFile.OpenAsync(Windows.Storage.FileAccessMode.Read)).AsStream(); //MediaStorageFile is a storage file from where you want to upload the file of your device
string fileheaderTemplate = "Content-Disposition: form-data; name=\"{0}\"" + _lineEnd + _lineEnd + "{1}" + _lineEnd;
long httpLength = 0;
foreach (var headerContent in _headerContents) // get the length of upload strem
httpLength += _boundarybytes.Length + Encoding.UTF8.GetBytes(string.Format(fileheaderTemplate, headerContent.Key, headerContent.Value)).Length;


httpLength += _boundarybytes.Length + Encoding.UTF8.GetBytes("Content-Disposition: form-data; name=\"uploadedFile\";filename=\"" + fileName + "\"" + _lineEnd).Length
+ Encoding.UTF8.GetBytes(_lineEnd).Length * 2 + _trailerbytes.Length;
httpWebRequest.ContentLength = httpLength + fStream.Length;  // wait until you upload your total stream


httpWebRequest.BeginGetRequestStream((result) =>
{
try
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
using (Stream stream = request.EndGetRequestStream(result))
{
foreach (var headerContent in _headerContents)
{
WriteToStream(stream, _boundarybytes);
WriteToStream(stream, string.Format(fileheaderTemplate, headerContent.Key, headerContent.Value));
}


WriteToStream(stream, _boundarybytes);
WriteToStream(stream, "Content-Disposition: form-data; name=\"uploadedFile\";filename=\"" + fileName + "\"" + _lineEnd);
WriteToStream(stream, _lineEnd);


int bytesRead = 0;
byte[] buffer = new byte[2048];  //upload 2K each time


while ((bytesRead = fStream.Read(buffer, 0, buffer.Length)) != 0)
{
stream.Write(buffer, 0, bytesRead);
Array.Clear(buffer, 0, 2048); // Clear the array.
}


WriteToStream(stream, _lineEnd);
WriteToStream(stream, _trailerbytes);
fStream.Close();
}
request.BeginGetResponse(a =>
{ //get response here
try
{
var response = request.EndGetResponse(a);
using (Stream streamResponse = response.GetResponseStream())
using (var memoryStream = new MemoryStream())
{
streamResponse.CopyTo(memoryStream);
responseBytes = memoryStream.ToArray();  // here I get byte response from server. you can change depends on server response
}
if (responseBytes.Length > 0 && responseBytes[0] == 1)
MessageBox.Show("Uploading Completed");
else
MessageBox.Show("Uploading failed, please try again.");
}
catch (Exception ex)
{}
}, null);
}
catch (Exception ex)
{
fStream.Close();
}
}, httpWebRequest);
}


private static void WriteToStream(Stream s, string txt)
{
byte[] bytes = Encoding.UTF8.GetBytes(txt);
s.Write(bytes, 0, bytes.Length);
}


private static void WriteToStream(Stream s, byte[] bytes)
{
s.Write(bytes, 0, bytes.Length);
}


private void SetEndHeaders()
{
_headerContents.Add("sId", LocalData.currentUser.SessionId);
_headerContents.Add("uId", LocalData.currentUser.UserIdentity);
_headerContents.Add("authServer", LocalData.currentUser.AuthServerIP);
_headerContents.Add("comPort", LocalData.currentUser.ComPort);
}

The below code reads a file, converts it to a byte array and then makes a request to the server.

    public void PostImage()
{
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();


byte[] imagebytearraystring = ImageFileToByteArray(@"C:\Users\Downloads\icon.png");
form.Add(new ByteArrayContent(imagebytearraystring, 0, imagebytearraystring.Count()), "profile_pic", "hello1.jpg");
HttpResponseMessage response = httpClient.PostAsync("your url", form).Result;


httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
}


private byte[] ImageFileToByteArray(string fullFilePath)
{
FileStream fs = File.OpenRead(fullFilePath);
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
fs.Close();
return bytes;
}

对于搜索403禁止的问题,而试图上传在多部分的形式下面可能有帮助,因为有一个情况取决于服务器配置,你会得到 MULTIPART _ STRICT _ ERROR”!由于不正确的 MultipartFormDataContent 头导致。 请注意,这两个图像标记/文件名变量都包含引号(“) eg filename="\"myfile.png\"" .

    MultipartFormDataContent form = new MultipartFormDataContent();
ByteArrayContent imageContent = new ByteArrayContent(fileBytes, 0, fileBytes.Length);
imageContent.Headers.TryAddWithoutValidation("Content-Disposition", "form-data; name="+imagetag+"; filename="+filename);
imageContent.Headers.TryAddWithoutValidation("Content-Type", "image / png");
form.Add(imageContent, imagetag, filename);

大家好,经过一天的网上搜索,我终于用下面的源代码解决了问题 希望能帮到你

    public UploadResult UploadFile(string  fileAddress)
{
HttpClient client = new HttpClient();


MultipartFormDataContent form = new MultipartFormDataContent();
HttpContent content = new StringContent("fileToUpload");
form.Add(content, "fileToUpload");
var stream = new FileStream(fileAddress, FileMode.Open);
content = new StreamContent(stream);
var fileName =
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "name",
FileName = Path.GetFileName(fileAddress),
};
form.Add(content);
HttpResponseMessage response = null;


var url = new Uri("http://192.168.10.236:2000/api/Upload2");
response = (client.PostAsync(url, form)).Result;


}

我也想上传的东西到一个服务器,它是一个 Spring 应用程序,我最终发现,我需要实际设置一个内容类型,它解释为一个文件。就像这样:

...
MultipartFormDataContent form = new MultipartFormDataContent();
var fileStream = new FileStream(uniqueTempPathInProject, FileMode.Open);
var streamContent = new StreamContent(fileStream);
streamContent.Headers.ContentType=new MediaTypeHeaderValue("application/zip");
form.Add(streamContent, "file",fileName);
...

顶部到@循环回答。

我们得到了以下错误, 无法连接到远程服务器

Fix: 在 Web.conff 中添加以下代码后,我们已经解决了配置问题

  <system.net>
<defaultProxy useDefaultCredentials="true" >
</defaultProxy>
</system.net>

下面是我将文件作为多种形式的数据发送时使用的方法:

    public T HttpPostMultiPartFileStream<T>(string requestURL, string filePath, string fileName)
{
string content = null;


using (MultipartFormDataContent form = new MultipartFormDataContent())
{
StreamContent streamContent;
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
streamContent = new StreamContent(fileStream);


streamContent.Headers.Add("Content-Type", "application/octet-stream");
streamContent.Headers.Add("Content-Disposition", string.Format("form-data; name=\"file\"; filename=\"{0}\"", fileName));
form.Add(streamContent, "file", fileName);


using (HttpClient client = GetAuthenticatedHttpClient())
{
HttpResponseMessage response = client.PostAsync(requestURL, form).GetAwaiter().GetResult();
content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();






try
{
return JsonConvert.DeserializeObject<T>(content);
}
catch (Exception ex)
{
// Log the exception
}


return default(T);
}
}
}
}

GetAuthenticatedHttpClient used above can be:

private HttpClient GetAuthenticatedHttpClient()
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(<yourBaseURL>));
httpClient.DefaultRequestHeaders.Add("Token, <yourToken>);
return httpClient;
}

下面是基本认证 C # 的多部分数据发布

public string UploadFilesToRemoteUrl(string url)
{
try
{


Dictionary<string, object> formFields = new Dictionary<string, object>();
formFields.Add("requestid", "{\"id\":\"idvalue\"}");


string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");


HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "multipart/form-data; boundary=" + boundary;


// basic authentication.
var username = "userid";
var password = "password";


string credidentials = username + ":" + password;
var authorization = Convert.ToBase64String(Encoding.Default.GetBytes(credidentials));
request.Headers["Authorization"] = "Basic " + authorization;


request.Method = "POST";
request.KeepAlive = true;


Stream memStream = new System.IO.MemoryStream();
WriteFormData(formFields, memStream, boundary);


FileInfo fileToUpload = new FileInfo(@"filelocation with name");
string fileFormKey = "file";
if (fileToUpload != null)
{
WritefileToUpload(fileToUpload, memStream, boundary, fileFormKey);
}
request.ContentLength = memStream.Length;


using (Stream requestStream = request.GetRequestStream())
{
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
}


using (var response = request.GetResponse())
{
Stream responseSReam = response.GetResponseStream();
StreamReader streamReader = new StreamReader(responseSReam);
return streamReader.ReadToEnd();
}
}
catch (WebException ex)
{
using (WebResponse response = ex.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse)response;
using (var streamReader = new StreamReader(response.GetResponseStream()))
return streamReader.ReadToEnd();


}
}
}


// write form id.
public static void WriteFormData(Dictionary<string, object> dictionary, Stream stream, string mimeBoundary)
{
string formdataTemplate = "\r\n--" + mimeBoundary +
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
if (dictionary != null)
{
foreach (string key in dictionary.Keys)
{
string formitem = string.Format(formdataTemplate, key, dictionary[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
stream.Write(formitembytes, 0, formitembytes.Length);
}
}
}


// write file.
public static void WritefileToUpload(FileInfo file, Stream stream, string mimeBoundary, string formkey)
{
var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + mimeBoundary + "\r\n");
var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + mimeBoundary + "--");


string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";


stream.Write(boundarybytes, 0, boundarybytes.Length);
var header = string.Format(headerTemplate, formkey, file.Name);
var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);


stream.Write(headerbytes, 0, headerbytes.Length);


using (var fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
{
var buffer = new byte[1024];
var bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
stream.Write(buffer, 0, bytesRead);
}
}
stream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
}

我知道这是老生常谈了,但我一直在与之斗争,我想分享我的解决方案。

该解决方案与 HttpClientMultipartFormDataContent一起工作,来自 System.Net.Http。您可以释放它与 .NET Core 1.0或更高,或 .NET Framework 4.5或更高。

作为一个快速总结,它是一个异步方法,它接收作为参数的 URL,您希望在其中执行 POST,一个用于发送字符串的键/值集合,以及一个用于发送文件的键/值集合。

private static async Task<HttpResponseMessage> Post(string url, NameValueCollection strings, NameValueCollection files)
{
var formContent = new MultipartFormDataContent(/* If you need a boundary, you can define it here */);


// Strings
foreach (string key in strings.Keys)
{
string inputName = key;
string content = strings[key];


formContent.Add(new StringContent(content), inputName);
}


// Files
foreach (string key in files.Keys)
{
string inputName = key;
string fullPathToFile = files[key];


FileStream fileStream = File.OpenRead(fullPathToFile);
var streamContent = new StreamContent(fileStream);
var fileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
formContent.Add(fileContent, inputName, Path.GetFileName(fullPathToFile));
}


var myHttpClient = new HttpClient();
var response = await myHttpClient.PostAsync(url, formContent);
//string stringContent = await response.Content.ReadAsStringAsync(); // If you need to read the content


return response;
}

You can prepare your POST like this (you can add so many strings and files as you need):

string url = @"http://yoursite.com/upload.php"


NameValueCollection strings = new NameValueCollection();
strings.Add("stringInputName1", "The content for input 1");
strings.Add("stringInputNameN", "The content for input N");


NameValueCollection files = new NameValueCollection();
files.Add("fileInputName1", @"FullPathToFile1"); // Path + filename
files.Add("fileInputNameN", @"FullPathToFileN");

最后,像这样调用方法:

var result = Post(url, strings, files).GetAwaiter().GetResult();

如果你愿意,你可以检查你的状态代码,并显示原因如下:

if (result.StatusCode == HttpStatusCode.OK)
{
// Logic if all was OK
}
else
{
// You can show a message like this:
Console.WriteLine(string.Format("Error. StatusCode: {0} | ReasonPhrase: {1}", result.StatusCode, result.ReasonPhrase));
}

如果有人需要它,这里我举一个小例子,说明如何用 PHP 接收存储文件(在我们的。网上应用程式) :

<?php


if (isset($_FILES['fileInputName1']) && $_FILES['fileInputName1']['error'] === UPLOAD_ERR_OK)
{
$fileTmpPath = $_FILES['fileInputName1']['tmp_name'];
$fileName = $_FILES['fileInputName1']['name'];


move_uploaded_file($fileTmpPath, '/the/final/path/you/want/' . $fileName);
}

我希望你会觉得有用,我很关注你的问题。

基于@Wolf5的回答,这对我很有用

var client = new WebClient();
client.Encoding = Encoding.UTF8;
var boundary = $"--------------------------{DateTime.Now.Ticks:x}";
client.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
client.Headers.Add("Cookie", cookie);


var start = $"--{boundary}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{Path.GetFileName(fileName)}\"\r\nContent-Type: image/jpeg\r\n\r\n";
var end = $"\r\n--{boundary}--\r\n";


var lst = new List<byte>();
lst.AddRange(client.Encoding.GetBytes(start));
lst.AddRange(File.ReadAllBytes(fileName));
lst.AddRange(client.Encoding.GetBytes(end));


var resp = client.UploadData($"{ApiUrl}/api/upload/image", "POST", lst.ToArray());

我知道这是一个老职位,但花了整个下午的努力,我不得不分享什么工作对我来说。我的解决方案是一个 Xamarin 应用程序,但是只要它是 C # ,代码仍然可以工作:

我的问题是,我想使用相同的端点和有效载荷作为我的 Angular 应用程序。(以下代码)。

    public class ApiService<T> where T : class
{
private string _webServiceUrl = Settings.WebServiceUrl;
private HttpClient httpClient;


public ApiService(string path = null)
{
_webServiceUrl = $"{_webServiceUrl}{path}/";


httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(_webServiceUrl);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Settings.Token);
}


private void HandleException(Exception ex, string url = "")
{
Settings.TotalHttpRequests -= 1;


Crashes.TrackError(ex, new Dictionary<string, string>{ { "URL", url }, });


MessagingCenter.Send<Page, string>(new Page(), "Exception", ex.Message);


}


public async Task<T> PostFormDataAsync(string url, string filePath, T t)
{
using (var form = new MultipartFormDataContent())
{
using (var fs = File.OpenRead(filePath))
{
byte[] bytes = new byte[fs.Length];


fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
fs.Close();


var json = JsonConvert.SerializeObject(t);
var data = new StringContent(json);


form.Add(new ByteArrayContent(bytes, 0, bytes.Length), "file", fs.Name);
form.Add(data, "data");


Settings.TotalHttpRequests += 1;


var result = await httpClient.PostAsync(url, form);


Settings.TotalHttpRequests -= 1;


if (result.IsSuccessStatusCode)
{
var content = await result.Content.ReadAsStringAsync();
var item = JsonConvert.DeserializeObject<T>(content);


return item;
}
else
{
await RaiseErrorAsync(result);


return default(T);
}
}
}
}


private async Task RaiseErrorAsync(HttpResponseMessage result)
{
var message = await result.Content.ReadAsStringAsync();


MessagingCenter.Send<Page, string>(new Page(), "Error", message);
}
}

我已经为其他 Xamarin 开发人员提供了一些代码。

我的 API 端点如下:

        [DisableRequestSizeLimit]
[Consumes("multipart/form-data")]
[HttpPost]
public async Task<ActionResult> Post()
{
try
{
var data = (Request.Form["data"]).ToString();
var myObject = JsonConvert.DeserializeObject<MyClass>(data);
var file = Request.Form.Files[0];
                

myObject = await _service.AddAsync(myObject, file);


var result = _mapper.Map<MyClassDto>(myObject);


return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}


}

从这里,我得到我的文件作为一个 IFormFile 实例。我还能够反序列化我发送的类型为 Tt的对象。

可以修改 ApiService 以实现 IApiService,这样您就可以从依赖服务中受益(使用 Xamarin)。

在角度方面,这是我得到的分量:

  onSubmit() {
this.submitted = true;
    

if (this.form.invalid) {return;}


if (this.fileToUpload == null) {
Swal.fire('File', 'Please attach the file', 'error');
return;
}


const formData = new FormData();
formData.append('file', this.fileToUpload, this.fileToUpload.name);
formData.append('data', JSON.stringify(this.form.value));


this.service.postEndpoint('', formData).subscribe((data) => {
//Do something here
});
}

服务内容:

import { ApiService } from '../api.service';


@Injectable({
providedIn: 'root'
})
export class MyService extends ApiService<MyClass>{


constructor(protected httpClient: HttpClient) {
super(httpClient, 'MyApiController');
}
}

应急服务:

const httpOptions = {
headers : new HttpHeaders({
Authorization: 'Bearer ' + localStorage.getItem('token')
})
};


export abstract class ApiService<T> {
basePath = environment.apiPath;
apiURL = `${this.basePath}api/`;


constructor(protected httpClient: HttpClient, protected actionUrl: string) { }


public postEndpoint(endPoint: string, model: any): Observable<any> {
return this.httpClient.post(this.apiURL + `${this.actionUrl}/${endPoint}`, model, httpOptions);
}
}

我希望这节省了一些人的时间! 快乐的编程!