UploadFile со значениями POST от WebClient
Я хочу загрузить файл на хост, используя класс WebClient. Я также хочу передать некоторые значения, которые должны отображаться в массиве $_POST на серверной части (PHP). Я хочу сделать это одним подключением
Я использовал код ниже
using (WebClient wc = new WebClient())
{
wc.Encoding = Encoding.UTF8;
NameValueCollection values = new NameValueCollection();
values.Add("client", "VIP");
values.Add("name", "John Doe");
wc.QueryString = values; // this displayes in $_GET
byte[] ans= wc.UploadFile(address, dumpPath);
}
Если я использовал свойство QueryString, значения отображаются в массиве $_GET. Но я хочу отправить его методом post
2 ответа
Там нет ничего встроенного, что позволяет вам сделать это. Я написал в блоге о расширении, которое вы могли бы использовать. Вот соответствующие классы:
public class UploadFile
{
public UploadFile()
{
ContentType = "application/octet-stream";
}
public string Name { get; set; }
public string Filename { get; set; }
public string ContentType { get; set; }
public Stream Stream { get; set; }
}
public byte[] UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values)
{
var request = WebRequest.Create(address);
request.Method = "POST";
var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
request.ContentType = "multipart/form-data; boundary=" + boundary;
boundary = "--" + boundary;
using (var requestStream = request.GetRequestStream())
{
// Write the values
foreach (string name in values.Keys)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
// Write the files
foreach (var file in files)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", file.Name, file.Filename, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", file.ContentType, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
file.Stream.CopyTo(requestStream);
buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--");
requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length);
}
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var stream = new MemoryStream())
{
responseStream.CopyTo(stream);
return stream.ToArray();
}
}
и теперь вы можете использовать его в своем приложении:
using (var stream = File.Open(dumpPath, FileMode.Open))
{
var files = new[]
{
new UploadFile
{
Name = "file",
Filename = Path.GetFileName(dumpPath),
ContentType = "text/plain",
Stream = stream
}
};
var values = new NameValueCollection
{
{ "client", "VIP" },
{ "name", "John Doe" },
};
byte[] result = UploadFiles(address, files, values);
}
Теперь в вашем PHP-скрипте вы можете использовать $_POST["client"]
, $_POST["name"]
а также $_FILES["file"]
,
Если кто-то хочет использовать решение @darin-dimitrov в асинхронном шаблоне с отчетами о проделанной работе, вот путь (для.NET 4.0):
public void UploadFileAsync(NameValueCollection values, Stream fileStream)
{
//to fire events on the calling thread
_asyncOperation = AsyncOperationManager.CreateOperation(null);
var ms = new MemoryStream();
//make a copy of the input stream in case sb uses disposable stream
fileStream.CopyTo(ms);
//you cannot set stream position often enough to zero
ms.Position = 0;
Task.Factory.StartNew(() =>
{
try
{
const string contentType = "application/octet-stream";
var request = WebRequest.Create(_url);
request.Method = "POST";
var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
request.ContentType = "multipart/form-data; boundary=" + boundary;
boundary = "--" + boundary;
var dataStream = new MemoryStream();
byte[] buffer;
// Write the values
foreach (string name in values.Keys)
{
buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
dataStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
dataStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
dataStream.Write(buffer, 0, buffer.Length);
}
// Write the file
buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
dataStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes($"Content-Disposition: form-data; name=\"file\"; filename=\"file\"{Environment.NewLine}");
dataStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", contentType, Environment.NewLine));
dataStream.Write(buffer, 0, buffer.Length);
ms.CopyTo(dataStream);
buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
dataStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(boundary + "--");
dataStream.Write(buffer, 0, buffer.Length);
dataStream.Position = 0;
//IMPORTANT: set content length to directly write to network socket
request.ContentLength = dataStream.Length;
var requestStream = request.GetRequestStream();
//Write data in chunks and report progress
var size = dataStream.Length;
const int chunkSize = 64 * 1024;
buffer = new byte[chunkSize];
long bytesSent = 0;
int readBytes;
while ((readBytes = dataStream.Read(buffer, 0, buffer.Length)) > 0)
{
requestStream.Write(buffer, 0, readBytes);
bytesSent += readBytes;
var status = "Uploading... " + bytesSent / 1024 + "KB of " + size / 1024 + "KB";
var percentage = Tools.Clamp(Convert.ToInt32(100 * bytesSent / size), 0, 100);
OnFileUploaderProgressChanged(new FileUploaderProgessChangedEventArgs(status, percentage));
}
//get response
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var stream = new MemoryStream())
{
// ReSharper disable once PossibleNullReferenceException - exception would get catched anyway
responseStream.CopyTo(stream);
var result = Encoding.Default.GetString(stream.ToArray());
OnFileUploaderCompleted(result == string.Empty
? new FileUploaderCompletedEventArgs(FileUploaderCompletedResult.Failed)
: new FileUploaderCompletedEventArgs(FileUploaderCompletedResult.Ok));
}
}
catch (Exception)
{
OnFileUploaderCompleted(new FileUploaderCompletedEventArgs(FileUploaderCompletedResult.Failed));
}
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}