通过HttpClient发布文件时,HttpRequest.Files为空

时间:2013-03-21 09:03:19

标签: c# .net asp.net-web-api httpclient

服务器端:

    public HttpResponseMessage Post([FromUri]string machineName)
    {
        HttpResponseMessage result = null;
        var httpRequest = HttpContext.Current.Request;

        if (httpRequest.Files.Count > 0 && !String.IsNullOrEmpty(machineName))
        ...

客户端:

    public static void PostFile(string url, string filePath)
    {
        if (String.IsNullOrWhiteSpace(url) || String.IsNullOrWhiteSpace(filePath))
            throw new ArgumentNullException();

        if (!File.Exists(filePath))
            throw new FileNotFoundException();

        using (var handler = new HttpClientHandler { Credentials=  new NetworkCredential(AppData.UserName, AppData.Password, AppCore.Domain) })
        using (var client = new HttpClient(handler))
        using (var content = new MultipartFormDataContent())
        using (var ms = new MemoryStream(File.ReadAllBytes(filePath)))
        {
            var fileContent = new StreamContent(ms);
            fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = Path.GetFileName(filePath)
            };
            content.Add(fileContent);
            content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            var result = client.PostAsync(url, content).Result;
            result.EnsureSuccessStatusCode();
        }
    }   

在服务器端,httpRequest.Files集合始终为空。但标题(内容长度等)是正确的。

4 个答案:

答案 0 :(得分:9)

您不应该使用HttpContext来获取ASP.NET Web API中的文件。看看这个由Microsoft编写的示例(http://code.msdn.microsoft.com/ASPNET-Web-API-File-Upload-a8c0fb0d/sourcecode?fileId=67087&pathId=565875642)。

public class UploadController : ApiController 
{ 
    public async Task<HttpResponseMessage> PostFile() 
    { 
        // Check if the request contains multipart/form-data. 
        if (!Request.Content.IsMimeMultipartContent()) 
        { 
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); 
        } 

        string root = HttpContext.Current.Server.MapPath("~/App_Data"); 
        var provider = new MultipartFormDataStreamProvider(root); 

        try 
        { 
            StringBuilder sb = new StringBuilder(); // Holds the response body 

            // Read the form data and return an async task. 
            await Request.Content.ReadAsMultipartAsync(provider); 

            // This illustrates how to get the form data. 
            foreach (var key in provider.FormData.AllKeys) 
            { 
                foreach (var val in provider.FormData.GetValues(key)) 
                { 
                    sb.Append(string.Format("{0}: {1}\n", key, val)); 
                } 
            } 

            // This illustrates how to get the file names for uploaded files. 
            foreach (var file in provider.FileData) 
            { 
                FileInfo fileInfo = new FileInfo(file.LocalFileName); 
                sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length)); 
            } 
            return new HttpResponseMessage() 
            { 
                Content = new StringContent(sb.ToString()) 
            }; 
        } 
        catch (System.Exception e) 
        { 
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); 
        } 
    } 

}

答案 1 :(得分:0)

试试这个方法:

    public void UploadFilesToRemoteUrl()
    {
        string[] files = { @"your file path" };

        string url = "Your url";
        long length = 0;
        string boundary = "----------------------------" +
        DateTime.Now.Ticks.ToString("x");

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

        Stream memStream = new System.IO.MemoryStream();

        byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
        boundary + "\r\n");

        string formdataTemplate = "\r\n--" + boundary +
        "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

        memStream.Write(boundarybytes, 0, boundarybytes.Length);

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

        for (int i = 0; i < files.Length; i++)
        {

            //string header = string.Format(headerTemplate, "file" + i, files[i]);
            string header = string.Format(headerTemplate, "uplTheFile", files[i]);

            byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);

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

            FileStream fileStream = new FileStream(files[i], FileMode.Open,
            FileAccess.Read);
            byte[] buffer = new byte[1024];

            int bytesRead = 0;

            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                memStream.Write(buffer, 0, bytesRead);
            }

            memStream.Write(boundarybytes, 0, boundarybytes.Length);
            fileStream.Close();
        }

        httpWebRequest2.ContentLength = memStream.Length;

        Stream requestStream = httpWebRequest2.GetRequestStream();

        memStream.Position = 0;
        byte[] tempBuffer = new byte[memStream.Length];
        memStream.Read(tempBuffer, 0, tempBuffer.Length);
        memStream.Close();
        requestStream.Write(tempBuffer, 0, tempBuffer.Length);
        requestStream.Close();

        WebResponse webResponse2 = httpWebRequest2.GetResponse();

        Stream stream2 = webResponse2.GetResponseStream();
        StreamReader reader2 = new StreamReader(stream2);

        webResponse2.Close();
        httpWebRequest2 = null;
        webResponse2 = null;
    }

答案 2 :(得分:0)

如果其他人遇到同样的问题:请确保您的边界字符串有效,例如: 这样做:

using (var content =
    new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
{
        ...
}

由于边界字符无效,可能是“/”日期分隔符。至少这解决了我在Context.Request.Files控制器中访问Nancy时遇到的问题(始终为空)。

最好使用类似DateTime.Now.Ticks.ToString("x")的内容。

答案 3 :(得分:0)

除了内容类型multipart/form-data之外,代码中的所有内容都很好看。请尝试更改代码以反映正确的内容类型:

content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");

您可能需要参考this帖子,了解为什么将内容类型设置为application/octet-stream在客户端没有意义。