如何使用HTTP POST multipart / form-data将文件上传到服务器?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用HTTP POST multipart / form-data将文件上传到服务器?相关的知识,希望对你有一定的参考价值。
我正在开发Windows Phone 8应用程序。我想通过php Web服务使用MIME类型multipart / form-data和名为“userid = SOME_ID”的字符串数据的HTTP POST请求上传SQLite数据库。
我不想使用像HttpClient,RestSharp或MyToolkit这样的第三方库。我尝试了下面的代码,但它没有上传文件,也没有给我任何错误。它在android,PHP等方面运行良好,因此在Web服务中没有问题。下面是我给出的代码(适用于WP8)。它出什么问题了?
我用Google搜索,我没有具体针对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();
}
我也尝试在Windows 8中解决我的问题,但它也无法正常工作。
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();
}
}
}
}
我使用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;
我还想把东西上传到服务器,它是一个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);
...
这是我最后的工作代码。我的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 + "
");
/// the last boundary.
byte[] trailer = Encoding.UTF8.GetBytes("
--" + boundary + "--
");
/// the form data, properly formatted
string formdataTemplate = "Content-Dis-data; name="{0}"
{1}";
/// the form-data file upload, properly formatted
string fileheaderTemplate = "Content-Dis-data; name="{0}"; filename="{1}";
Content-Type: {2}
";
/// 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, "
");
/// 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, "
");
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;
}
我非常感谢Darin Rousseau帮助我。
这个简单的版本也有效。
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}
Content-Disposition: form-data; name="file"; filename="{1}"
Content-Type: {2}
{3}
--{0}--
", boundary, filename, contentType, fileData);
var nfile = webClient.Encoding.GetBytes(package);
byte[] resp = webClient.UploadData(url, "POST", nfile);
}
如果需要,添加任何额外的必需标头
我一直在玩一点,并提出了一个简化的,更通用的解决方案:
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("
--" + boundary + "
");
// The last boundary
byte[] trailer = System.Text.En以上是关于如何使用HTTP POST multipart / form-data将文件上传到服务器?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过HttpClient去POST一个multipart/form-data数据
PyQt5 和 Django:如何使用 HTTP 请求(Multipart-form)上传图像?
使用 RestSharp 发送 HTTP POST Multipart/form-data 字段
如何在 axios 中为 POST - multipart/form-data 设置 MIME 类型?