简体   繁体   中英

HttpPost and webapi

I have created an API which takes a file as input and processes it. The sample is like this...

[HttpPost]
    public string ProfileImagePost(HttpPostedFile HttpFile)
    {

      //rest of the code
     }

Then I have creted a Client to consume this as follows...

 string path = @"abc.csv";
        FileStream rdr = new FileStream(path, FileMode.Open, FileAccess.Read);
        byte[] inData = new byte[rdr.Length];
        rdr.Read(inData, 0, Convert.ToInt32(rdr.Length));

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost/abc/../ProfileImagePost");
        req.KeepAlive = false;
        req.ContentType = "multipart/form-data"; 
        req.Method = "POST";
        req.ContentLength = rdr.Length;
        req.AllowWriteStreamBuffering = true;

        Stream reqStream = req.GetRequestStream();

        reqStream.Write(inData, 0, Convert.ToInt32(rdr.Length));
        reqStream.Close();
        HttpWebResponse TheResponse = (HttpWebResponse)req.GetResponse();
        string TheResponseString1 = new StreamReader(TheResponse.GetResponseStream(), Encoding.ASCII).ReadToEnd();
        TheResponse.Close();

But I get 500 error at on client side. Help me out of it guys.

Thanx in advance...

The ASP.NET Web API doesn't work with HttpPostedFile . Instead you should use a MultipartFormDataStreamProvider as shown in the following tutorial .

Also your client side call is wrong. You have set the ContentType to multipart/form-data but you are not respecting this encoding at all. You are simply writing the file to the request stream.

So let's take an example:

public class UploadController : ApiController
{
    public Task<HttpResponseMessage> Post()
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

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

        // Read the form data
        return Request.Content.ReadAsMultipartAsync(provider).ContinueWith(t =>
        {
            // This illustrates how to get the file names.
            foreach (MultipartFileData file in provider.FileData)
            {
                Trace.WriteLine(file.Headers.ContentDisposition.FileName);
                Trace.WriteLine("Server file path: " + file.LocalFileName);
            }
            return Request.CreateResponse(HttpStatusCode.OK);
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
}

and then you could use an HttpClient to call this API:

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;

class Program
{
    static void Main(string[] args)
    {
        using (var client = new HttpClient())
        using (var content = new MultipartFormDataContent())
        {
            client.BaseAddress = new Uri("http://localhost:16724/");
            var fileContent = new ByteArrayContent(File.ReadAllBytes(@"c:\work\foo.txt"));
            fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = "Foo.txt"
            };
            content.Add(fileContent);
            var result = client.PostAsync("/api/upload", content).Result;
            Console.WriteLine(result.StatusCode);
        }
    }
}

Instead of HttpPostedFile , directly send file as stream from client and at server side read File as stream like:

 //read uploaded csv file at server side
 Stream csvStream = HttpContext.Current.Request.Files[0].InputStream;

//Send file from client 
 public static void PostFile()
 {
       string[] files = { @"C:\Test.csv" };

        string url = "http://localhost/abc/../test.xml";
        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;
    }

You should stick to the webapi route naming conventions to save yourself some trouble.

All methods called PostSomething() will be accepted as HttpPost. Their parameter signature will tell them apart of you need two with the same name.

So call your WebApi method PostProfileImage(HttpPostedFile file), then you can post to http:///api// with the file as data.

Getting the route basics wrong in WebApi is the root cause of HTTP/500's and will derive you of exceptions.

Here is my code for posting screenshots the client side

    public void PostMethod()
    {
    ImageConverter converter = new ImageConverter();
    var bytes = (byte[])converter.ConvertTo(bmpScreenshot, typeof(byte[]));
    StringConverter s = new StringConverter();

    string uri = "http://localhost:3844/api/upload";

    byte[] postBytes = bytes;
    string str = Properties.Settings.Default.token.ToString(); //after login user receives a response token, it is stored in the application settings. All Posts save in db with a this token

    byte[] bA = ASCIIEncoding.ASCII.GetBytes(str);

    MultipartFormDataContent multiPartData = new MultipartFormDataContent();

    ByteArrayContent byteArrayContent = new ByteArrayContent(postBytes);
    ByteArrayContent bAC = new ByteArrayContent(bA);
    multiPartData.Add(bAC, "token");
    multiPartData.Add(byteArrayContent,"picture");

    HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, uri);
    requestMessage.Content = multiPartData;

    HttpClient httpClient = new HttpClient();
    Task<HttpResponseMessage> httpRequest = httpClient.SendAsync(requestMessage);
    HttpResponseMessage httpResponse = httpRequest.Result;
    HttpContent responseContent = httpResponse.Content;
}

the server side

public class UploadController : ApiController
    {
public masterEntities context = new masterEntities();
public ImgEntitySet imgEntity = new ImgEntitySet();
public async Task<HttpResponseMessage> PostRawBufferManual()
{
MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider("~/App_Data");
MultipartFileStreamProvider dataContent = await Request.Content.ReadAsMultipartAsync(streamProvider);
            foreach (HttpContent data in dataContent.Contents)
            {
                string fileName = data.Headers.ContentDisposition.Name;
                byte[] n = await data.ReadAsByteArrayAsync();
                string m = Encoding.ASCII.GetString(n);
                int z = int.Parse(m);
                imgEntity.UID = z;
                break;
            }
            foreach (HttpContent data in dataContent.Contents)
            {
                string fileNamePicture = data.Headers.ContentDisposition.Name;
                if (fileNamePicture == "picture")
                {
                    byte[] b = await data.ReadAsByteArrayAsync();
                    imgEntity.Image = b;
                }
            }

            context.ImgEntitySet.Add(imgEntity);
            context.SaveChanges();
            return Request.CreateResponse(HttpStatusCode.OK );
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM