如何使用WebRequest POST文件

时间:2018-02-23 14:04:53

标签: c# .net api file-upload webrequest

我想在API服务器之间模拟传输文件。 首先,我创建了一个接收上传文件的API。 并使用Postman成功上传文件。 这是接收的代码。

[AllowAnonymous]
[HttpPost]
[Route("api/data/UploadFile")]
public IHttpActionResult UploadFile()
{
    if (HttpContext.Current.Request.Files.AllKeys.Any())
    {
        var httpPostedFile = HttpContext.Current.Request.Files["UploadedImage"];

        if (httpPostedFile != null)
        {
            var fileSavePath = Path.Combine(HttpContext.Current.Server.MapPath("~/images"), "Capture1.PNG");

            httpPostedFile.SaveAs(fileSavePath);
        }
    }

    return Ok("SUCCESS");
}

我尝试像邮差一样上传。 Postman Upload

现在,我想使用此代码从另一个API使用WebRequest上传文件。

[AllowAnonymous]
[HttpGet]
[Route("api/data/TestUpload")]
public IHttpActionResult TestUpload()
{
    string formdataTemplate = "Content-Disposition: form-data; filename=\"{0}\";\r\nContent-Type: image/png\r\n\r\n";
    string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
    byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost/iisapi/api/data/UploadFile");
    request.ServicePoint.Expect100Continue = false;
    request.Method = "POST";
    request.ContentType = "multipart/form-data; boundary=" + boundary;

    string filePath = Path.Combine(HttpContext.Current.Server.MapPath("~/images"), "Capture2.PNG");

    using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        using (Stream requestStream = request.GetRequestStream())
        {
            requestStream.Write(boundarybytes, 0, boundarybytes.Length);
            string formitem = string.Format(formdataTemplate, "UploadedImage");
            byte[] formbytes = Encoding.UTF8.GetBytes(formitem);
            requestStream.Write(formbytes, 0, formbytes.Length);
            byte[] buffer = new byte[fileStream.Length];
            int bytesLeft = 0;

            while ((bytesLeft = fileStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                requestStream.Write(buffer, 0, bytesLeft);
            }

        }
    }

    try
    {
        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { }

        return Ok("SUCCESS");
    }
    catch (Exception ex)
    {
        throw;
    }
}

如果我拨打TestUpload API,则会成功进入UploadFile功能。但是,在使用此代码HttpContext.Current.Request.Files.AllKeys.Any()检查请求中是否存在文件时,它将返回false。请求中没有文件。我在这里缺少什么?

谢谢。

1 个答案:

答案 0 :(得分:0)

public virtual async Task<TResponse> PostFileAsync<TResponse>(string url, Dictionary<string, string> headers, FileResponse fileData, IProgress<ProgressCompleted> progress, CancellationToken token)
    {
        using (var request = new HttpRequestMessage(HttpMethod.Post, url))
        {
            List<byte> byteData = new List<byte>();
            Action<double> actionProgress = null;

            if (progress != null)
            {
                actionProgress = (progressValue) => progress.Report(new ProgressCompleted(progressValue));
            }
            var boundary = string.Format("----------{0:N}", Guid.NewGuid());

            var multiContent = new MultipartFormDataContent(boundary);

            foreach (var customHeader in headers)
            {
                request.Headers.Add(customHeader.Key, customHeader.Value);
            }

            var content = new ByteArrayContent(fileData.FileData);
            content.Headers.TryAddWithoutValidation("Content-Type", fileData.FileType);
            multiContent.Add(content, "file", fileData.FileName);

            request.Content = multiContent;

            using (var response = await Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false))
            {
                var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
                var canReportProgress = total != -1 && progress != null;
                if (!response.IsSuccessStatusCode)
                    RestExceptionHandlerService.Handle(response.StatusCode);

                using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                {
                    var totalRead = 0L;
                    var buffer = new byte[BufferSize];
                    var isMoreToRead = true;

                    do
                    {
                        token.ThrowIfCancellationRequested();

                        var read = await stream.ReadAsync(buffer, 0, buffer.Length, token).ConfigureAwait(false);
                        if (read == 0)
                        {
                            isMoreToRead = false;
                        }
                        else
                        {
                            if (read != buffer.Length)
                            {
                                byte[] cpArray = new byte[read];
                                Array.Copy(buffer, cpArray, read);
                                byteData.AddRange(cpArray);
                            }
                            else {
                                byteData.AddRange(buffer);
                            }
                            totalRead += read;
                            if (canReportProgress)
                            {
                                progress.Report(new ProgressCompleted((double)totalRead / total * 100));
                            }
                        }
                    } while (isMoreToRead);
                }

                //TODO: server returns just string NOT Json
                return (TResponse)(object) Encoding.UTF8.GetString(byteData.ToArray(), 0, byteData.Count);
            }
        }
    }