Tworzę aplikację na Windows Phone 8. Chcę załadować bazę danych SQLite przez usługę sieciową PHP przy użyciu żądania HTTP POST z typem MIME multipart / form-data i ciągiem danych o nazwie „userid = SOME_ID”.
Nie chcę używać bibliotek innych firm, takich jak HttpClient, RestSharp lub MyToolkit. Wypróbowałem poniższy kod, ale nie przesyła pliku, a także nie wyświetla żadnych błędów. Działa dobrze w systemie Android, PHP itp., Więc nie ma problemu z usługą sieciową. Poniżej znajduje się mój podany kod (dla WP8). co jest z tym nie tak?
Wyszukałem w Google i nie podchodzę do WP8
async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(DBNAME);
//Below line gives me file with 0 bytes, why? Should I use
//IsolatedStorageFile instead of StorageFile
//var file = await ApplicationData.Current.LocalFolder.GetFileAsync(DBNAME);
byte[] fileBytes = null;
using (var stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}
//var res = await HttpPost(Util.UPLOAD_BACKUP, fileBytes);
HttpPost(fileBytes);
}
private void HttpPost(byte[] file_bytes)
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.myserver.com/upload.php");
httpWebRequest.ContentType = "multipart/form-data";
httpWebRequest.Method = "POST";
var asyncResult = httpWebRequest.BeginGetRequestStream((ar) => { GetRequestStreamCallback(ar, file_bytes); }, httpWebRequest);
}
private void GetRequestStreamCallback(IAsyncResult asynchronousResult, byte[] postData)
{
//DON'T KNOW HOW TO PASS "userid=some_user_id"
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
Stream postStream = request.EndGetRequestStream(asynchronousResult);
postStream.Write(postData, 0, postData.Length);
postStream.Close();
var asyncResult = request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
streamResponse.Close();
streamRead.Close();
response.Close();
}
Próbowałem też rozwiązać swój problem w Windows 8, ale to też nie działa.
public async Task Upload(byte[] fileBytes)
{
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture)))
{
content.Add(new StreamContent(new MemoryStream(fileBytes)));
//Not sure below line is true or not
content.Add(new StringContent("userid=farhanW8"));
using (var message = await client.PostAsync("http://www.myserver.com/upload.php", content))
{
var input = await message.Content.ReadAsStringAsync();
}
}
}
}
c#
php
post
windows-phone-8
multipartform-data
Farhan Ghumra
źródło
źródło
var fileStream = new FileStream(filePath, FileMode.Open); form.Add(new StreamContent(fileStream), "profile_pic");
Oto mój ostatni działający kod. Moja usługa sieciowa potrzebowała jednego pliku (nazwa parametru POST to „plik”) i wartości ciągu (nazwa parametru POST to „identyfikator_użytkownika”).
/// <summary> /// Occurs when upload backup application bar button is clicked. Author : Farhan Ghumra /// </summary> private async void btnUploadBackup_Click(object sender, EventArgs e) { var dbFile = await ApplicationData.Current.LocalFolder.GetFileAsync(Util.DBNAME); var fileBytes = await GetBytesAsync(dbFile); var Params = new Dictionary<string, string> { { "userid", "9" } }; UploadFilesToServer(new Uri(Util.UPLOAD_BACKUP), Params, Path.GetFileName(dbFile.Path), "application/octet-stream", fileBytes); } /// <summary> /// Creates HTTP POST request & uploads database to server. Author : Farhan Ghumra /// </summary> private void UploadFilesToServer(Uri uri, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData) { string boundary = "----------" + DateTime.Now.Ticks.ToString("x"); HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri); httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary; httpWebRequest.Method = "POST"; httpWebRequest.BeginGetRequestStream((result) => { try { HttpWebRequest request = (HttpWebRequest)result.AsyncState; using (Stream requestStream = request.EndGetRequestStream(result)) { WriteMultipartForm(requestStream, boundary, data, fileName, fileContentType, fileData); } request.BeginGetResponse(a => { try { var response = request.EndGetResponse(a); var responseStream = response.GetResponseStream(); using (var sr = new StreamReader(responseStream)) { using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) { string responseString = streamReader.ReadToEnd(); //responseString is depend upon your web service. if (responseString == "Success") { MessageBox.Show("Backup stored successfully on server."); } else { MessageBox.Show("Error occurred while uploading backup on server."); } } } } catch (Exception) { } }, null); } catch (Exception) { } }, httpWebRequest); } /// <summary> /// Writes multi part HTTP POST request. Author : Farhan Ghumra /// </summary> private void WriteMultipartForm(Stream s, string boundary, Dictionary<string, string> data, string fileName, string fileContentType, byte[] fileData) { /// The first boundary byte[] boundarybytes = Encoding.UTF8.GetBytes("--" + boundary + "\r\n"); /// the last boundary. byte[] trailer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); /// the form data, properly formatted string formdataTemplate = "Content-Dis-data; name=\"{0}\"\r\n\r\n{1}"; /// the form-data file upload, properly formatted string fileheaderTemplate = "Content-Dis-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n"; /// Added to track if we need a CRLF or not. bool bNeedsCRLF = false; if (data != null) { foreach (string key in data.Keys) { /// if we need to drop a CRLF, do that. if (bNeedsCRLF) WriteToStream(s, "\r\n"); /// Write the boundary. WriteToStream(s, boundarybytes); /// Write the key. WriteToStream(s, string.Format(formdataTemplate, key, data[key])); bNeedsCRLF = true; } } /// If we don't have keys, we don't need a crlf. if (bNeedsCRLF) WriteToStream(s, "\r\n"); WriteToStream(s, boundarybytes); WriteToStream(s, string.Format(fileheaderTemplate, "file", fileName, fileContentType)); /// Write the file data to the stream. WriteToStream(s, fileData); WriteToStream(s, trailer); } /// <summary> /// Writes string to stream. Author : Farhan Ghumra /// </summary> private void WriteToStream(Stream s, string txt) { byte[] bytes = Encoding.UTF8.GetBytes(txt); s.Write(bytes, 0, bytes.Length); } /// <summary> /// Writes byte array to stream. Author : Farhan Ghumra /// </summary> private void WriteToStream(Stream s, byte[] bytes) { s.Write(bytes, 0, bytes.Length); } /// <summary> /// Returns byte array from StorageFile. Author : Farhan Ghumra /// </summary> private async Task<byte[]> GetBytesAsync(StorageFile file) { byte[] fileBytes = null; using (var stream = await file.OpenReadAsync()) { fileBytes = new byte[stream.Size]; using (var reader = new DataReader(stream)) { await reader.LoadAsync((uint)stream.Size); reader.ReadBytes(fileBytes); } } return fileBytes; }
Jestem bardzo wdzięczny Darinowi Rousseau za pomoc.
źródło
Ta uproszczona wersja również działa.
public void UploadMultipart(byte[] file, string filename, string contentType, string url) { var webClient = new WebClient(); string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x"); webClient.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary); var fileData = webClient.Encoding.GetString(file); var package = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n{3}\r\n--{0}--\r\n", boundary, filename, contentType, fileData); var nfile = webClient.Encoding.GetBytes(package); byte[] resp = webClient.UploadData(url, "POST", nfile); }
W razie potrzeby dodaj dodatkowe wymagane nagłówki.
źródło
MultipartFormDataContent
nieudanych zmaganiach z tym podejściem zadziałało. Jest to mniej efektowne, ale jeśli potrzebujesz szczegółowej kontroli nad wiadomością HTTP, jest to dobre rozwiązanie.Trochę się bawiłem i wymyśliłem uproszczone, bardziej ogólne rozwiązanie:
private static string sendHttpRequest(string url, NameValueCollection values, NameValueCollection files = null) { string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); // The first boundary byte[] boundaryBytes = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n"); // The last boundary byte[] trailer = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); // The first time it itereates, we need to make sure it doesn't put too many new paragraphs down or it completely messes up poor webbrick byte[] boundaryBytesF = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n"); // Create the request and set parameters HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); request.ContentType = "multipart/form-data; boundary=" + boundary; request.Method = "POST"; request.KeepAlive = true; request.Credentials = System.Net.CredentialCache.DefaultCredentials; // Get request stream Stream requestStream = request.GetRequestStream(); foreach (string key in values.Keys) { // Write item to stream byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}", key, values[key])); requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); requestStream.Write(formItemBytes, 0, formItemBytes.Length); } if (files != null) { foreach(string key in files.Keys) { if(File.Exists(files[key])) { int bytesRead = 0; byte[] buffer = new byte[2048]; byte[] formItemBytes = System.Text.Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", key, files[key])); requestStream.Write(boundaryBytes, 0, boundaryBytes.Length); requestStream.Write(formItemBytes, 0, formItemBytes.Length); using (FileStream fileStream = new FileStream(files[key], FileMode.Open, FileAccess.Read)) { while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { // Write file content to stream, byte by byte requestStream.Write(buffer, 0, bytesRead); } fileStream.Close(); } } } } // Write trailer and close stream requestStream.Write(trailer, 0, trailer.Length); requestStream.Close(); using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream())) { return reader.ReadToEnd(); }; }
Możesz go używać w ten sposób:
string fileLocation = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "somefile.jpg"; NameValueCollection values = new NameValueCollection(); NameValueCollection files = new NameValueCollection(); values.Add("firstName", "Alan"); files.Add("profilePicture", fileLocation); sendHttpRequest("http://example.com/handler.php", values, files);
A w skrypcie PHP możesz obsłużyć takie dane:
echo $_POST['firstName']; $name = $_POST['firstName']; $image = $_FILES['profilePicture']; $ds = DIRECTORY_SEPARATOR; move_uploaded_file($image['tmp_name'], realpath(dirname(__FILE__)) . $ds . "uploads" . $ds . $image['name']);
źródło
Możesz użyć tej klasy:
using System.Collections.Specialized; class Post_File { public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) { string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); byte[] boundarybytesF = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n"); // the first time it itereates, you need to make sure it doesn't put too many new paragraphs down or it completely messes up poor webbrick. HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); wr.Method = "POST"; wr.KeepAlive = true; wr.Credentials = System.Net.CredentialCache.DefaultCredentials; wr.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; var nvc2 = new NameValueCollection(); nvc2.Add("Accepts-Language", "en-us,en;q=0.5"); wr.Headers.Add(nvc2); wr.ContentType = "multipart/form-data; boundary=" + boundary; Stream rs = wr.GetRequestStream(); bool firstLoop = true; string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; foreach (string key in nvc.Keys) { if (firstLoop) { rs.Write(boundarybytesF, 0, boundarybytesF.Length); firstLoop = false; } else { rs.Write(boundarybytes, 0, boundarybytes.Length); } string formitem = string.Format(formdataTemplate, key, nvc[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); rs.Write(formitembytes, 0, formitembytes.Length); } rs.Write(boundarybytes, 0, boundarybytes.Length); string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; string header = string.Format(headerTemplate, paramName, new FileInfo(file).Name, contentType); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); rs.Write(headerbytes, 0, headerbytes.Length); FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[4096]; int bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { rs.Write(buffer, 0, bytesRead); } fileStream.Close(); byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); rs.Write(trailer, 0, trailer.Length); rs.Close(); WebResponse wresp = null; try { wresp = wr.GetResponse(); Stream stream2 = wresp.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); } catch (Exception ex) { if (wresp != null) { wresp.Close(); wresp = null; } } finally { wr = null; } } }
Użyj tego:
NameValueCollection nvc = new NameValueCollection(); //nvc.Add("id", "TTR"); nvc.Add("table_name", "uploadfile"); nvc.Add("commit", "uploadfile"); Post_File.HttpUploadFile("http://example/upload_file.php", @"C:\user\yourfile.docx", "uploadfile", "application/vnd.ms-excel", nvc);
przykładowy serwer
upload_file.php
:m('File upload '.(@copy($_FILES['uploadfile']['tmp_name'],getcwd().'\\'.'/'.$_FILES['uploadfile']['name']) ? 'success' : 'failed')); function m($msg) { echo '<div style="background:#f1f1f1;border:1px solid #ddd;padding:15px;font:14px;text-align:center;font-weight:bold;">'; echo $msg; echo '</div>'; }
źródło
Oto, co zadziałało dla mnie podczas wysyłania pliku jako danych wieloformatowych:
public T HttpPostMultiPartFileStream<T>(string requestURL, string filePath, string fileName) { string content = null; using (MultipartFormDataContent form = new MultipartFormDataContent()) { StreamContent streamContent; using (var fileStream = new FileStream(filePath, FileMode.Open)) { streamContent = new StreamContent(fileStream); streamContent.Headers.Add("Content-Type", "application/octet-stream"); streamContent.Headers.Add("Content-Disposition", string.Format("form-data; name=\"file\"; filename=\"{0}\"", fileName)); form.Add(streamContent, "file", fileName); using (HttpClient client = GetAuthenticatedHttpClient()) { HttpResponseMessage response = client.PostAsync(requestURL, form).GetAwaiter().GetResult(); content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); try { return JsonConvert.DeserializeObject<T>(content); } catch (Exception ex) { // Log the exception } return default(T); } } } }
GetAuthenticatedHttpClient użyty powyżej może być:
private HttpClient GetAuthenticatedHttpClient() { HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(<yourBaseURL>)); httpClient.DefaultRequestHeaders.Add("Token, <yourToken>); return httpClient; }
źródło
MultipartFormDataContent
Pomysł, którego szukałem.Poniższy kod czyta plik, konwertuje go na tablicę bajtów, a następnie wysyła żądanie do serwera.
public void PostImage() { HttpClient httpClient = new HttpClient(); MultipartFormDataContent form = new MultipartFormDataContent(); byte[] imagebytearraystring = ImageFileToByteArray(@"C:\Users\Downloads\icon.png"); form.Add(new ByteArrayContent(imagebytearraystring, 0, imagebytearraystring.Count()), "profile_pic", "hello1.jpg"); HttpResponseMessage response = httpClient.PostAsync("your url", form).Result; httpClient.Dispose(); string sd = response.Content.ReadAsStringAsync().Result; } private byte[] ImageFileToByteArray(string fullFilePath) { FileStream fs = File.OpenRead(fullFilePath); byte[] bytes = new byte[fs.Length]; fs.Read(bytes, 0, Convert.ToInt32(fs.Length)); fs.Close(); return bytes; }
źródło
Cześć chłopaki, po jednym dniu wyszukiwania w sieci wreszcie rozwiązuję problem z poniższym kodem źródłowym, mam nadzieję, że ci pomogę
public UploadResult UploadFile(string fileAddress) { HttpClient client = new HttpClient(); MultipartFormDataContent form = new MultipartFormDataContent(); HttpContent content = new StringContent("fileToUpload"); form.Add(content, "fileToUpload"); var stream = new FileStream(fileAddress, FileMode.Open); content = new StreamContent(stream); var fileName = content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = "name", FileName = Path.GetFileName(fileAddress), }; form.Add(content); HttpResponseMessage response = null; var url = new Uri("http://192.168.10.236:2000/api/Upload2"); response = (client.PostAsync(url, form)).Result; }
źródło
Oto wieloczęściowy post danych z podstawowym uwierzytelnianiem C #
public string UploadFilesToRemoteUrl(string url) { try { Dictionary<string, object> formFields = new Dictionary<string, object>(); formFields.Add("requestid", "{\"id\":\"idvalue\"}"); string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.ContentType = "multipart/form-data; boundary=" + boundary; // basic authentication. var username = "userid"; var password = "password"; string credidentials = username + ":" + password; var authorization = Convert.ToBase64String(Encoding.Default.GetBytes(credidentials)); request.Headers["Authorization"] = "Basic " + authorization; request.Method = "POST"; request.KeepAlive = true; Stream memStream = new System.IO.MemoryStream(); WriteFormData(formFields, memStream, boundary); FileInfo fileToUpload = new FileInfo(@"filelocation with name"); string fileFormKey = "file"; if (fileToUpload != null) { WritefileToUpload(fileToUpload, memStream, boundary, fileFormKey); } request.ContentLength = memStream.Length; using (Stream requestStream = request.GetRequestStream()) { memStream.Position = 0; byte[] tempBuffer = new byte[memStream.Length]; memStream.Read(tempBuffer, 0, tempBuffer.Length); memStream.Close(); requestStream.Write(tempBuffer, 0, tempBuffer.Length); } using (var response = request.GetResponse()) { Stream responseSReam = response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseSReam); return streamReader.ReadToEnd(); } } catch (WebException ex) { using (WebResponse response = ex.Response) { HttpWebResponse httpResponse = (HttpWebResponse)response; using (var streamReader = new StreamReader(response.GetResponseStream())) return streamReader.ReadToEnd(); } } } // write form id. public static void WriteFormData(Dictionary<string, object> dictionary, Stream stream, string mimeBoundary) { string formdataTemplate = "\r\n--" + mimeBoundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}"; if (dictionary != null) { foreach (string key in dictionary.Keys) { string formitem = string.Format(formdataTemplate, key, dictionary[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); stream.Write(formitembytes, 0, formitembytes.Length); } } } // write file. public static void WritefileToUpload(FileInfo file, Stream stream, string mimeBoundary, string formkey) { var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + mimeBoundary + "\r\n"); var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + mimeBoundary + "--"); string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n"; stream.Write(boundarybytes, 0, boundarybytes.Length); var header = string.Format(headerTemplate, formkey, file.Name); var headerbytes = System.Text.Encoding.UTF8.GetBytes(header); stream.Write(headerbytes, 0, headerbytes.Length); using (var fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read)) { var buffer = new byte[1024]; var bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { stream.Write(buffer, 0, bytesRead); } } stream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); }
źródło
Działa na telefon z okienkiem 8.1. Możesz tego spróbować.
Dictionary<string, object> _headerContents = new Dictionary<string, object>(); const String _lineEnd = "\r\n"; const String _twoHyphens = "--"; const String _boundary = "*****"; private async void UploadFile_OnTap(object sender, System.Windows.Input.GestureEventArgs e) { Uri serverUri = new Uri("http:www.myserver.com/Mp4UploadHandler", UriKind.Absolute); string fileContentType = "multipart/form-data"; byte[] _boundarybytes = Encoding.UTF8.GetBytes(_twoHyphens + _boundary + _lineEnd); byte[] _trailerbytes = Encoding.UTF8.GetBytes(_twoHyphens + _boundary + _twoHyphens + _lineEnd); Dictionary<string, object> _headerContents = new Dictionary<string, object>(); SetEndHeaders(); // to add some extra parameter if you need httpWebRequest = (HttpWebRequest)WebRequest.Create(serverUri); httpWebRequest.ContentType = fileContentType + "; boundary=" + _boundary; httpWebRequest.Method = "POST"; httpWebRequest.AllowWriteStreamBuffering = false; // get response after upload header part var fileName = Path.GetFileName(MediaStorageFile.Path); Stream fStream = (await MediaStorageFile.OpenAsync(Windows.Storage.FileAccessMode.Read)).AsStream(); //MediaStorageFile is a storage file from where you want to upload the file of your device string fileheaderTemplate = "Content-Disposition: form-data; name=\"{0}\"" + _lineEnd + _lineEnd + "{1}" + _lineEnd; long httpLength = 0; foreach (var headerContent in _headerContents) // get the length of upload strem httpLength += _boundarybytes.Length + Encoding.UTF8.GetBytes(string.Format(fileheaderTemplate, headerContent.Key, headerContent.Value)).Length; httpLength += _boundarybytes.Length + Encoding.UTF8.GetBytes("Content-Disposition: form-data; name=\"uploadedFile\";filename=\"" + fileName + "\"" + _lineEnd).Length + Encoding.UTF8.GetBytes(_lineEnd).Length * 2 + _trailerbytes.Length; httpWebRequest.ContentLength = httpLength + fStream.Length; // wait until you upload your total stream httpWebRequest.BeginGetRequestStream((result) => { try { HttpWebRequest request = (HttpWebRequest)result.AsyncState; using (Stream stream = request.EndGetRequestStream(result)) { foreach (var headerContent in _headerContents) { WriteToStream(stream, _boundarybytes); WriteToStream(stream, string.Format(fileheaderTemplate, headerContent.Key, headerContent.Value)); } WriteToStream(stream, _boundarybytes); WriteToStream(stream, "Content-Disposition: form-data; name=\"uploadedFile\";filename=\"" + fileName + "\"" + _lineEnd); WriteToStream(stream, _lineEnd); int bytesRead = 0; byte[] buffer = new byte[2048]; //upload 2K each time while ((bytesRead = fStream.Read(buffer, 0, buffer.Length)) != 0) { stream.Write(buffer, 0, bytesRead); Array.Clear(buffer, 0, 2048); // Clear the array. } WriteToStream(stream, _lineEnd); WriteToStream(stream, _trailerbytes); fStream.Close(); } request.BeginGetResponse(a => { //get response here try { var response = request.EndGetResponse(a); using (Stream streamResponse = response.GetResponseStream()) using (var memoryStream = new MemoryStream()) { streamResponse.CopyTo(memoryStream); responseBytes = memoryStream.ToArray(); // here I get byte response from server. you can change depends on server response } if (responseBytes.Length > 0 && responseBytes[0] == 1) MessageBox.Show("Uploading Completed"); else MessageBox.Show("Uploading failed, please try again."); } catch (Exception ex) {} }, null); } catch (Exception ex) { fStream.Close(); } }, httpWebRequest); } private static void WriteToStream(Stream s, string txt) { byte[] bytes = Encoding.UTF8.GetBytes(txt); s.Write(bytes, 0, bytes.Length); } private static void WriteToStream(Stream s, byte[] bytes) { s.Write(bytes, 0, bytes.Length); } private void SetEndHeaders() { _headerContents.Add("sId", LocalData.currentUser.SessionId); _headerContents.Add("uId", LocalData.currentUser.UserIdentity); _headerContents.Add("authServer", LocalData.currentUser.AuthServerIP); _headerContents.Add("comPort", LocalData.currentUser.ComPort); }
źródło
Dla osób szukających zabronionego problemu 403 podczas próby przesłania w formie wieloczęściowej poniższe może pomóc, ponieważ w zależności od konfiguracji serwera, w zależności od konfiguracji serwera, otrzymasz MULTIPART_STRICT_ERROR "! @Eq 0" z powodu nieprawidłowych nagłówków MultipartFormDataContent. Należy pamiętać, że obie zmienne imagetag / filename zawierają cudzysłowy (\ "), np. Filename =" \ "myfile.png \" ".
MultipartFormDataContent form = new MultipartFormDataContent(); ByteArrayContent imageContent = new ByteArrayContent(fileBytes, 0, fileBytes.Length); imageContent.Headers.TryAddWithoutValidation("Content-Disposition", "form-data; name="+imagetag+"; filename="+filename); imageContent.Headers.TryAddWithoutValidation("Content-Type", "image / png"); form.Add(imageContent, imagetag, filename);
źródło
Chciałem też przesłać rzeczy na serwer i była to aplikacja Spring. W końcu odkryłem, że muszę dokładnie ustawić typ zawartości, aby zinterpretował ją jako plik. Takie jak to:
... MultipartFormDataContent form = new MultipartFormDataContent(); var fileStream = new FileStream(uniqueTempPathInProject, FileMode.Open); var streamContent = new StreamContent(fileStream); streamContent.Headers.ContentType=new MediaTypeHeaderValue("application/zip"); form.Add(streamContent, "file",fileName); ...
źródło
Od góry do odpowiedzi @loop.
Otrzymaliśmy poniższy błąd dla Asp.Net MVC, Nie można połączyć się ze zdalnym serwerem
Poprawka: Po dodaniu poniższego kodu w Web.Confing problem został dla nas rozwiązany
<system.net> <defaultProxy useDefaultCredentials="true" > </defaultProxy> </system.net>
źródło
Wiem, że to jest i stary wątek, ale walczyłem z tym i chciałbym podzielić się swoim rozwiązaniem.
To rozwiązanie działa z
HttpClient
iMultipartFormDataContent
zSystem.Net.Http
. Możesz zwolnić go z.NET Core 1.0
lub wyższą.NET Framework 4.5
lub wyższą.Krótko mówiąc, jest to metoda asynchroniczna, która jako parametry otrzymuje adres URL, w którym chcesz wykonać POST, zbiór kluczy / wartości do wysyłania ciągów oraz kolekcję kluczy / wartości do wysyłania plików.
private static async Task<HttpResponseMessage> Post(string url, NameValueCollection strings, NameValueCollection files) { var formContent = new MultipartFormDataContent(/* If you need a boundary, you can define it here */); // Strings foreach (string key in strings.Keys) { string inputName = key; string content = strings[key]; formContent.Add(new StringContent(content), inputName); } // Files foreach (string key in files.Keys) { string inputName = key; string fullPathToFile = files[key]; FileStream fileStream = File.OpenRead(fullPathToFile); var streamContent = new StreamContent(fileStream); var fileContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result); formContent.Add(fileContent, inputName, Path.GetFileName(fullPathToFile)); } var myHttpClient = new HttpClient(); var response = await myHttpClient.PostAsync(url, formContent); //string stringContent = await response.Content.ReadAsStringAsync(); // If you need to read the content return response; }
Możesz przygotować swój POST w ten sposób (możesz dodać tyle ciągów znaków i plików, ile potrzebujesz):
string url = @"http://yoursite.com/upload.php" NameValueCollection strings = new NameValueCollection(); strings.Add("stringInputName1", "The content for input 1"); strings.Add("stringInputNameN", "The content for input N"); NameValueCollection files = new NameValueCollection(); files.Add("fileInputName1", @"FullPathToFile1"); // Path + filename files.Add("fileInputNameN", @"FullPathToFileN");
Na koniec wywołaj metodę w ten sposób:
var result = Post(url, strings, files).GetAwaiter().GetResult();
Jeśli chcesz, możesz sprawdzić swój kod statusu i pokazać powód, jak poniżej:
if (result.StatusCode == HttpStatusCode.OK) { // Logic if all was OK } else { // You can show a message like this: Console.WriteLine(string.Format("Error. StatusCode: {0} | ReasonPhrase: {1}", result.StatusCode, result.ReasonPhrase)); }
A jeśli ktoś tego potrzebuje, tutaj podam mały przykład jak odebrać zapisz plik z PHP (po drugiej stronie naszej aplikacji .Net):
<?php if (isset($_FILES['fileInputName1']) && $_FILES['fileInputName1']['error'] === UPLOAD_ERR_OK) { $fileTmpPath = $_FILES['fileInputName1']['tmp_name']; $fileName = $_FILES['fileInputName1']['name']; move_uploaded_file($fileTmpPath, '/the/final/path/you/want/' . $fileName); }
Mam nadzieję, że uznasz to za przydatne, zwracam uwagę na Twoje pytania.
źródło
Async().Result
nie jest asyncstreamContent.ReadAsByteArrayAsync().Result
. AleGetAwaiter().GetResult()
też nie jest asynchroniczny