Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过WebClient上载具有POST值的文件_C#_Php_File Upload_Web - Fatal编程技术网

C# 通过WebClient上载具有POST值的文件

C# 通过WebClient上载具有POST值的文件,c#,php,file-upload,web,C#,Php,File Upload,Web,我想使用WebClient类将文件上载到主机。我还想传递一些值,这些值应该显示在服务器部件(PHP)上的$\u POST数组中。我想一个接一个 我用了下面的代码 using (WebClient wc = new WebClient()) { wc.Encoding = Encoding.UTF8; NameValueCollection values = new NameValueCollection(); values.Add("client", "VIP");

我想使用WebClient类将文件上载到主机。我还想传递一些值,这些值应该显示在服务器部件(PHP)上的$\u POST数组中。我想一个接一个

我用了下面的代码

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属性,$\u GET数组中显示的值。但是我想通过post方法发送它。

没有内置的方法允许您这样做。我有一个你可以使用的分机。以下是相关课程:

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();
    }
}

现在,在您的PHP脚本中,您可以使用
$\u POST[“client”]
$\u POST[“name”]
$\u FILES[“file”]

如果有人想以异步模式使用@darin dimitrov的解决方案并进行进度报告,这是一种方法(对于.NET 4.0):


这里有一个类似的问题,您可能想检查答案,使其与进度指示异步的步骤是什么?HttpWebClient上的同步函数应替换为它们的异步对应函数:Begin/EndGetRequestStream、Begin/EndGetResponse,…谢谢您的代码!如果您使用的是MVC4,则可能会出现以下异常:“MIME多部分流意外结束。”。MIME多部分消息未完成。'框架()中存在错误,需要在最后一个边界处添加新行:var boundaryBuffer=Encoding.ASCII.GetBytes(boundary+“--”+Environment.NewLine);如果有人想在Mono(linux/Mac)上运行此功能,您可能需要更改
环境。换行符
以显式使用
\r\n
,因为,第5.9节规定此选项应始终为
CRLF
。我还没有测试过这个。感谢您填补了Web API中的巨大空白,@DarinI收到了400个错误请求,因为http内容末尾没有额外的换行符。。lolHi,谢谢你的代码,我很想在我的项目中实现它,但我对这一部分有一些疑问:onFileUploaderCompleteDeventargs(结果==string.Empty?新建FileUploaderCompletedEventArgs(FileUploaderCompletedResult.Failed):新建FileUploaderCompletedEventArgs(FileUploaderCompletedResult.Ok));如何声明“FileUploaderCompletedResult”?
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);
}
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);
}