0

我有以下支持将文件发布到服务器的 .net web api 控制器方法。

    public Task<HttpResponseMessage> PostFile()
            {
                var request = Request;
                if (!request.Content.IsMimeMultipartContent())
                {
                    throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType));
                }

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

                var task = request.Content.ReadAsMultipartAsy

nc(provider).ContinueWith(o =>
            {
                var finfo = new FileInfo(provider.FileData.First().LocalFileName);

                var guid = Guid.NewGuid().ToString();

                File.Move(finfo.FullName,
                    Path.Combine(root,
                        guid + "_" + provider.FileData.First().Headers.ContentDisposition.FileName.Replace("\"", "")));

                return new HttpResponseMessage
                {
                    Content = new StringContent("File upload.")
                };
            });

            return task;
        }

这很好用,但是我希望能够在帖子中包含一些关于文件的元数据。目前我对元数据有不同的 web api 方法,比如

  public HttpResponseMessage PostTAG(TAG tag)

它获取标签对象中的信息并将其保存到数据库中。如果我的 api 客户端可以在一个请求中将文件和元数据一起发布,那会容易得多。这在.net web api中是否可行。

4

1 回答 1

0

有可能,您的 WEB API 为 TAG 数据声明一个参数。问题将是您的客户将数据发布到您的 WEB API。如果您的客户端使用 .NET 将数据发布到您的 WEB API,.NET WebClient 不支持将文件与数据一起发布

因此,您将需要使用较低级别的 HttpWebRequest,例如这个

public string UploadFilesToRemoteUrl(string url, Dictionary<string, string> files, NameValueCollection nvc, string contenttype)
        {
            string boundary = "----------------------------" +
            DateTime.Now.Ticks.ToString("x");

            HttpWebRequest httpWebRequest2 = (HttpWebRequest)GetWebRequest(new Uri(url)); //(HttpWebRequest)WebRequest.Create(url);
            SetProxy(httpWebRequest2);
            SetUserAgent(httpWebRequest2);
            httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary;
            httpWebRequest2.Timeout = WebRequestTimeout; // 60 second * miliseconds * 60 minutes = 1 hour
            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}";

            if (nvc != null)
            {
                foreach (string key in nvc.Keys)
                {
                    string formitem = string.Format(formdataTemplate, key, nvc[key]);
                    byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
                    memStream.Write(formitembytes, 0, formitembytes.Length);
                }
            }

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

            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n\r\n";
            if (string.IsNullOrEmpty(contenttype) == false)
            {
                headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" + contenttype + "\r\n";
            }

            string[] keys = nvc.AllKeys;
            foreach (KeyValuePair<string, string> key in files)
            {
                //string header = string.Format(headerTemplate, "file" + i, files[i]);
                //string header = string.Format(headerTemplate, "uplTheFile", files[i]);
                string header = string.Format(headerTemplate, key.Key, key.Value);
                byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);

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

                FileStream fileStream = new FileStream(key.Value, FileMode.Open, FileAccess.Read);
                byte[] buffer = new byte[buffsize];

                int bytesRead = 0;

                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                    int progress = Convert.ToInt32((memStream.Length * 100) / fileStream.Length);
                    ReportProgress(key.Value, progress);
                }

                memStream.Write(boundarybytes, 0, boundarybytes.Length);
                fileStream.Close();
                if (MonitoredDownload != null) MonitoredDownload.OnComplete(key.Value);
                buffer = null;
                headerbytes = null;
            }

            httpWebRequest2.ContentLength = memStream.Length;

            Stream requestStream = httpWebRequest2.GetRequestStream();
            memStream.Position = 0;
            byte[] tempBuffer = new byte[buffsize];
            int bytereads = 0;
            while ((bytereads = memStream.Read(tempBuffer, 0, tempBuffer.Length)) != 0)
            {
                requestStream.Write(tempBuffer, 0, bytereads);
            }

            //memStream.Read(tempBuffer, 0, tempBuffer.Length);
            memStream.Close();
            memStream.Dispose();
            //requestStream.Write(tempBuffer, 0, tempBuffer.Length);
            requestStream.Close();
            requestStream.Dispose();

            WebResponse webResponse2 = httpWebRequest2.GetResponse();
            //SaveCookie(webResponse2, new Uri(url).GetLeftPart(UriPartial.Authority));
            Stream stream2 = webResponse2.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            string str = reader2.ReadToEnd();
            reader2.Close();
            reader2.Dispose();

            stream2.Close();
            stream2.Dispose();
            webResponse2.Close();

            httpWebRequest2 = null;
            webResponse2 = null;
            tempBuffer = null;
            return str;
        }

要使用它,只需调用

Dictionary<string,string> dict = new Dictionary<string,string>();
dict.Add("file1","c:\\myfile1.jpg");
NamuValueCollection nvc = new NameValueCollection();
nvc.Add("GPSPosition","somegpsvalue");
nvc.Add("CameraModel","somecameramodel");
UploadFilesToRemoteUrl("http://www.remoteurl.com/upload", dict, metadata, "Content-Type: application/octet-stream\r\n");

上面的代码摘自 WebScraper 项目http://www.sorainnosia.com/Projects#WS

于 2013-11-05T03:39:09.950 回答