How to send a request to upload image file to LINE server with multipart/form-data for posting image to LINE Notify? - vb.net

I'm trying to post an image from local using LINE Notify, but get bad request, how to send the right request using HttpWebRequest with multipart/form-data content-type in vb.net?
I've tried on cURL, and it's woking:
curl -i -X POST https://notify-api.line.me/api/notify -H "Authorization: Bearer <TOKEN>" -F "message=test" -F "imageFile=#C:\PATH\to\file.jpg"
Here is what I've done in vb.net:
Imports System.IO
Imports System.Net
Imports System.Security.Cryptography
Imports System.Text
Public Class Form1
Private Sub btnPic_Click(sender As Object, e As EventArgs) Handles btnPic.Click
OpenFileDialog1.Filter = "Image File (*.jpg)|*.jpg;*.JPG |Image File (*.png)|*.png;*.PNG"
OpenFileDialog1.FileName = ""
If OpenFileDialog1.ShowDialog() <> DialogResult.Cancel Then
txtPic.Text = OpenFileDialog1.FileName
End If
End Sub
Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
' [references]
'https://notify-bot.line.me/doc/en/
'http://white5168.blogspot.com/2017/01/line-notify-6-line-notify.html
'https://aprico-media.com/posts/1824
'https://stackoverflow.com/questions/3890754/using-httpwebrequest-to-post-data-upload-image-using-multipart-form-data
Dim md5Hash As MD5 = MD5.Create()
'Boundary string
Dim strBound As String = "---------------------" & GetMd5Hash(md5Hash, CInt(Int((654321 * Rnd()) + 1))).Substring(0, 10)
Try
Dim request = DirectCast(WebRequest.Create("https://notify-api.line.me/api/notify"), HttpWebRequest)
Dim postData As String = "--" & strBound & vbCrLf
postData += "Content-Disposition: form-data; name=""message""" & vbCrLf & vbCrLf
postData += txtText.Text & vbCrLf
' [Not working] sticker part
'postData += "--" & strBound & vbCrLf
'postData += "Content-Disposition: form-data; name=""stickerPackageId""" & vbCrLf & vbCrLf
'postData += 1 & vbCrLf
'postData += "--" & strBound & vbCrLf
'postData += "Content-Disposition: form-data; name=""stickerId""" & vbCrLf & vbCrLf
'postData += 2 & vbCrLf
If txtPic.Text <> "" Then
Dim ext As String = Path.GetExtension(txtPic.Text)
If ext = ".jpg" Then
ext = "jpeg"
ElseIf ext = ".png" Then
ext = "png"
Else
MessageBox.Show("Sorry! LINE Notify supports only jpeg/png image file.")
btnPic.PerformClick()
Return
End If
' [Not working] image part
postData += "--" & strBound & vbCrLf
postData += "Content-Disposition: form-data; name=""imageFile""; filename=""" & Path.GetFileName(txtPic.Text) & """" & vbCrLf
postData += "Content-Type: image/" & ext & vbCrLf & vbCrLf
postData += Convert.ToBase64String(File.ReadAllBytes(txtPic.Text)) & vbCrLf
End If
postData += vbCrLf & "--" & strBound & "--"
Dim data = Encoding.UTF8.GetBytes(postData)
request.Method = "POST"
request.ContentType = "multipart/form-data; boundary=" & strBound
request.ContentLength = data.Length
request.Headers.Add("Authorization", "Bearer <TOKEN>")
Using stream = request.GetRequestStream()
stream.Write(data, 0, data.Length)
End Using
Dim response = DirectCast(request.GetResponse(), HttpWebResponse)
Dim responseString = New StreamReader(response.GetResponseStream()).ReadToEnd()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)
End Try
End Sub
Shared Function GetMd5Hash(ByVal md5Hash As MD5, ByVal Input As String) As String
' Convert the input string to a byte array and compute the hash.
Dim data As Byte() = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(Input))
' Create a new Stringbuilder to collect the bytes
' and create a string.
Dim sBuilder As New StringBuilder()
' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
Dim i As Integer
For i = 0 To data.Length - 1
sBuilder.Append(data(i).ToString("x2"))
Next i
' Return the hexadecimal string.
Return sBuilder.ToString()
End Function 'GetMd5Hash
End Class
There is no problem for sending only "message", whenever the other parts i.e."imageFile", "stickerPackageId", "stickerId",... are combined with, the result is getting error (400). However, if a field name is changed to small letter as i.e."stickerpackageid", "stickerid" vb will not catch any exception, but just send the "message" to Notify. So, I think a wrong part should be in http request string, or does it needed to convert each field into binary array? If that is the case how to obtain the right result?

POST multipart/form-data for line notify , need generate output byte array list by yourself
LINE Notify API Reference https://notify-bot.line.me/doc/en/
Upload File Class
public class FormFile
{
public string Name { get; set; }
public string ContentType { get; set; }
public string FilePath { get; set; }
public byte[] bytes { get; set; }
}
Test Data
private void multipartTest(string access_token)
{
Dictionary<string, object> d = new Dictionary<string, object>()
{
// message , imageFile ... name is provided by LINE API
{ "message", #"message..." },
{ "imageFile", new FormFile(){ Name = "notify.jpg", ContentType = "image/jpeg", FilePath="notify.jpg" }
}
};
string boundary = "Boundary";
List<byte[]> output = genMultPart(d, boundary);
lineNotifyMultipart(access_token, boundary, output);
}
C# Code
private void lineNotifyMultipart(string access_token, string boundary, List<byte[]> output)
{
try
{
#region POST multipart/form-data
StringBuilder sb = new StringBuilder();
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(lineNotifyURL);
request.Method = "POST";
request.ContentType = "multipart/form-data; boundary=Boundary";
request.Timeout = 30000;
// header
sb.Clear();
sb.Append("Bearer ");
sb.Append(access_token);
request.Headers.Add("Authorization", sb.ToString());
// note: multipart/form-data boundary must exist in headers ContentType
sb.Clear();
sb.Append("multipart/form-data; boundary=");
sb.Append(boundary);
request.ContentType = sb.ToString();
// write Post Body Message
BinaryWriter bw = new BinaryWriter(request.GetRequestStream());
foreach(byte[] bytes in output)
bw.Write(bytes);
#endregion
getResponse(request);
}
catch (Exception ex)
{
#region Exception
StringBuilder sbEx = new StringBuilder();
sbEx.Append(ex.GetType());
sbEx.AppendLine();
sbEx.AppendLine(ex.Message);
sbEx.AppendLine(ex.StackTrace);
if (ex.InnerException != null)
sbEx.AppendLine(ex.InnerException.Message);
myException ex2 = new myException(sbEx.ToString());
//message(ex2.Message);
#endregion
}
}
private void getResponse(HttpWebRequest request)
{
StringBuilder sb = new StringBuilder();
string result = string.Empty;
StreamReader sr = null;
try
{
#region Get Response
if (request == null)
return;
// HttpWebRequest GetResponse() if error happened will trigger WebException
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
sb.AppendLine();
foreach (var x in response.Headers)
{
sb.Append(x);
sb.Append(" : ");
sb.Append(response.Headers[x.ToString()]);
if (x.ToString() == "X-RateLimit-Reset")
{
sb.Append(" ( ");
sb.Append(CheckFormat.ToEpcohDateTimeUTC(long.Parse(response.Headers[x.ToString()])));
sb.Append(" )");
}
sb.AppendLine();
}
using (sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
sb.Append(result);
}
}
//message(sb.ToString());
#endregion
}
catch (WebException ex)
{
#region WebException handle
// WebException Response
using (HttpWebResponse response = (HttpWebResponse)ex.Response)
{
sb.AppendLine("Error");
foreach (var x in response.Headers)
{
sb.Append(x);
sb.Append(" : ");
sb.Append(response.Headers[x.ToString()]);
sb.AppendLine();
}
using (sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
sb.Append(result);
}
//message(sb.ToString());
}
#endregion
}
}
public List<byte[]> genMultPart(Dictionary<string, object> parameters, string boundary)
{
StringBuilder sb = new StringBuilder();
sb.Clear();
sb.Append("\r\n--");
sb.Append(boundary);
sb.Append("\r\n");
string beginBoundary = sb.ToString();
sb.Clear();
sb.Append("\r\n--");
sb.Append(boundary);
sb.Append("--\r\n");
string endBoundary = sb.ToString();
sb.Clear();
sb.Append("Content-Type: multipart/form-data; boundary=");
sb.Append(boundary);
sb.Append("\r\n");
List<byte[]> byteList = new List<byte[]>();
byteList.Add(System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
foreach (KeyValuePair<string, object> pair in parameters)
{
if (pair.Value is FormFile)
{
byteList.Add(System.Text.Encoding.ASCII.GetBytes(beginBoundary));
FormFile form = pair.Value as FormFile;
sb.Clear();
sb.Append("Content-Disposition: form-data; name=\"");
sb.Append(pair.Key);
sb.Append("\"; filename=\"");
sb.Append(form.Name);
sb.Append("\"\r\nContent-Type: ");
sb.Append(form.ContentType);
sb.Append("\r\n\r\n");
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
byteList.Add(bytes);
if (form.bytes == null && !string.IsNullOrEmpty(form.FilePath))
{
FileStream fs = new FileStream(form.FilePath, FileMode.Open, FileAccess.Read);
MemoryStream ms = new MemoryStream();
fs.CopyTo(ms);
byteList.Add(ms.ToArray());
}
else
byteList.Add(form.bytes);
}
else
{
byteList.Add(System.Text.Encoding.ASCII.GetBytes(beginBoundary));
sb.Clear();
sb.Append("Content-Disposition: form-data; name=\"");
sb.Append(pair.Key);
sb.Append("\"");
sb.Append("\r\n\r\n");
sb.Append(pair.Value);
string data = sb.ToString();
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
byteList.Add(bytes);
}
}
byteList.Add(System.Text.Encoding.ASCII.GetBytes(endBoundary));
return byteList;
}

Related

Uploading File as FormData in vb.net?

I'm having trouble uploading some form data to an API endpoint in vb.net.
Example From Vendor:
curl -X POST -H 'Authorization: Token token=sfg999666t673t7t82'
-H 'Content-Type: multipart/form-data' -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
-F file=#/Users/user1/Downloads/download.jpeg -F file_name=nameForFile
-F is_shared=true -F targetable_id=1 -F targetable_type=Lead -X POST "https://domain.freshsales.io/api/documents"
VB.NET CODE
Shameless pulled from (Upload files with HTTPWebrequest (multipart/form-data))
Private Sub HttpUploadFile(ByVal filePath As String, ByVal fileParameterName As String, ByVal contentType As String, ByVal otherParameters As Specialized.NameValueCollection)
Dim boundary As String = "---------------------------" & DateTime.Now.Ticks.ToString("x")
Dim newLine As String = System.Environment.NewLine
Dim boundaryBytes As Byte() = Text.Encoding.ASCII.GetBytes(newLine & "--" & boundary & newLine)
Dim request As Net.HttpWebRequest = Net.WebRequest.Create("https://domain.freshsales.io/api/documents")
request.ContentType = "multipart/form-data; boundary=" & boundary
request.Method = "POST"
request.KeepAlive = True
Using requestStream As IO.Stream = request.GetRequestStream()
Dim formDataTemplate As String = "Content-Disposition: form-data; name=""{0}""{1}{1}{2}"
For Each key As String In otherParameters.Keys
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)
Dim formItem As String = String.Format(formDataTemplate, key, newLine, otherParameters(key))
Dim formItemBytes As Byte() = Text.Encoding.UTF8.GetBytes(formItem)
requestStream.Write(formItemBytes, 0, formItemBytes.Length)
Next key
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)
Dim headerTemplate As String = "Content-Disposition: form-data; name=""{0}""; filename=""{1}""{2}Content-Type: {3}{2}{2}"
Dim header As String = String.Format(headerTemplate, fileParameterName, filePath, newLine, contentType)
Dim headerBytes As Byte() = Text.Encoding.UTF8.GetBytes(header)
requestStream.Write(headerBytes, 0, headerBytes.Length)
Using fileStream As New IO.FileStream(filePath, IO.FileMode.Open, IO.FileAccess.Read)
Dim buffer(4096) As Byte
Dim bytesRead As Int32 = fileStream.Read(buffer, 0, buffer.Length)
Do While (bytesRead > 0)
requestStream.Write(buffer, 0, bytesRead)
bytesRead = fileStream.Read(buffer, 0, buffer.Length)
Loop
End Using
Dim trailer As Byte() = Text.Encoding.ASCII.GetBytes(newLine & "--" + boundary + "--" & newLine)
requestStream.Write(trailer, 0, trailer.Length)
End Using
Dim response As Net.WebResponse = Nothing
Try
response = request.GetResponse()
Using responseStream As IO.Stream = response.GetResponseStream()
Using responseReader As New IO.StreamReader(responseStream)
Dim responseText = responseReader.ReadToEnd()
Diagnostics.Debug.Write(responseText)
End Using
End Using
Catch exception As Net.WebException
response = exception.Response
If (response IsNot Nothing) Then
Using reader As New IO.StreamReader(response.GetResponseStream())
Dim responseText = reader.ReadToEnd()
Diagnostics.Debug.Write(responseText)
End Using
response.Close()
End If
Finally
request = Nothing
End Try
End Sub
Calling The Function
Here is my call:
Dim headers As NameValueCollection = New NameValueCollection()
headers.Add("Token", "token=youguessedit;")
Dim nvc As NameValueCollection = New NameValueCollection()
nvc.Add("is_shared", true)
nvc.Add("targetable_id", 1)
nvc.Add("targetable_type", "Lead")
HttpUploadFile("c:\test\file.pdf", "file", "application/pdf", nvc, headers);
I think part of my issue is in the way the headers are attached here:
Dim headerTemplate As String = "Content-Disposition: form-data; name=""{0}""; filename=""{1}""{2}Content-Type: {3}{2}{2}"
In that the API endpoint is expecting file= and file_name= how can I correct the headers?
Can anyone point out where else I have gone wrong? Is there an easier way of doing this?
Here's a simple Console app example using HttpClient with a MultipartFormDataContent which takes care of all the headers and streaming the file, this example also works as-is thanks to Postman-Echo, if there's a requirement for additional headers (only Token is shown here) be sure to add them to the HttpClient.DefaultRequestHeaders
Dim response As New HttpResponseMessage
Dim path As String = "C:\\Temp\\upload.pdf"
Dim uri As New Uri("https://postman-echo.com/post")
Using form As New MultipartFormDataContent,
fs As New FileStream(path, FileMode.Open),
content As New StreamContent(fs),
httpClient As New HttpClient
form.Add(content)
httpClient.DefaultRequestHeaders.Add("Token", "Super Secret")
response = httpClient.PostAsync(uri, form).GetAwaiter.GetResult()
Console.WriteLine("Is Successfull: " & response.IsSuccessStatusCode)
End Using
EDIT: Cleaned up nested Using statements

Creating new tasks with the Wrike API and VB.net

I'm having trouble creating new Wrike tasks using VB.net and the Wrike API. I however, am able to connect to Wrike to GET a list of folders so I know I'm able to successfully authenticate.
Link to task creation docs:
https://developers.wrike.com/documentation/api/methods/create-task
The only required field is "Title"
Dim accessToken As String = API_Token
Dim apiVersion As String = "v4"
Dim ApiBaseUrl As String = "https://www.wrike.com"
Dim folderID As String = "Some Folder ID Here"
Dim address As String = ApiBaseUrl & "/api/" & apiVersion & "/folders/" & folderID & "/tasks"
Dim result As String
Dim task_str_ As String = "importance=Normal&description=Test task description&dates={""start"":""2019-07-24"",""due"":""2019-07-30""}&title=Task Created With VS&status=Active"
Try
Dim request As HttpWebRequest = TryCast(WebRequest.Create(address), HttpWebRequest)
request.Headers.Add("Authorization", "Bearer " & accessToken)
request.Method = "PUT"
request.ContentType = "application/json"
Using requestWriter2 As New StreamWriter(request.GetRequestStream())
requestWriter2.Write(task_str_)
End Using
Dim webResp As WebResponse = request.GetResponse()
Using reader = New StreamReader(webResp.GetResponseStream)
result = reader.ReadToEnd()
End Using
TextBox1.Text = (result)
Catch ex As Exception
TextBox1.Text = ex.ToString
End Try
Here is the error I'm receiving:
System.Net.WebException: The remote server returned an error: (400) Bad Request
Once I made the suggested changes, everything works good.
Dim accessToken As String = API_Token
Dim apiVersion As String = "v4"
Dim ApiBaseUrl As String = "https://www.wrike.com"
Dim folderID As String = "Some Folder ID Here"
Dim address As String = ApiBaseUrl & "/api/" & apiVersion & "/folders/" & folderID & "/tasks"
Dim result As String
Dim task_str_ As String = "importance=Normal&description=Test task description&dates={""start"":""2019-07-24"",""due"":""2019-07-30""}&title=Task Created With VS&status=Active"
Try
Dim request As HttpWebRequest = TryCast(WebRequest.Create(address), HttpWebRequest)
request.Headers.Add("Authorization", "Bearer " & accessToken)
request.Method = "POST"
request.ContentLength = task_str_.Length
request.ContentType = "application/x-www-form-urlencoded"
Using requestWriter2 As New StreamWriter(request.GetRequestStream())
requestWriter2.Write(task_str_)
End Using
Dim webResp As WebResponse = request.GetResponse()
Using reader = New StreamReader(webResp.GetResponseStream)
result = reader.ReadToEnd()
End Using
TextBox1.Text = (result)
Catch ex As Exception
TextBox1.Text = ex.ToString
End Try

Prestashop - Unable to upload a new image product with the prestashop 1.6 webservice

I'm trying to upload a new image for a product with the prestashop webservice through a vb .net application, but I get the following error message:
"Unable to save this image".
The URL used to upload the image is this: http://localhost/prestashop/api/images/products/1
And the source code of the function that make the request is this:
Public Sub executeAddImage(ByVal resource As String, ByVal id As String, ByVal imageToAdd As Image)
Dim response As String = Nothing
Try
Dim ms As New MemoryStream()
imageToAdd.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg)
Dim byteArray As Byte() = ms.ToArray()
Dim requestUrl As String = Me.WebServiceURL & "/" & resource & "/" & id
MsgBox(requestUrl)
Dim webRequest As HttpWebRequest = DirectCast(System.Net.WebRequest.Create(requestUrl), HttpWebRequest)
webRequest.Method = WebServicePrestashop.CRUDMethod.Create
'webRequest.ContentType = "image/jpeg"
webRequest.ContentType = "application/x-www-form-urlencoded"
webRequest.Credentials = New NetworkCredential(Me.LoginName, WebServicePrestashop._password)
webRequest.ContentLength = byteArray.Length
MsgBox(byteArray.Length)
' Get the request stream
Using dataStream As Stream = webRequest.GetRequestStream()
dataStream.Write(byteArray, 0, byteArray.Length)
End Using
' Get the response
Using webResponse As HttpWebResponse = DirectCast(webRequest.GetResponse(), HttpWebResponse)
If webResponse.StatusCode = HttpStatusCode.OK Then
Using reader As New StreamReader(webResponse.GetResponseStream(), Encoding.UTF8)
Dim imageNew As Image = Image.FromStream(webResponse.GetResponseStream())
End Using
End If
End Using
Catch ex As WebException
MsgBox(ex.Message.ToString())
Dim reader As New StreamReader(ex.Response.GetResponseStream)
MsgBox(reader.ReadToEnd)
End Try
End Sub
I'm using the HTTP POST method, and the POST content is the bynary content of the new image.
How can I fix it?.
Here the solution.
I think the key is that I must write the body of the webrequest programatically adding to the stream of the webrequest the boundary (in binary array format), the Content-Type chain (in binary array format) and the content of the image to upload (in binary array format).
Public Sub executeAddImage(ByVal resource As String, ByVal id As String, ByVal imageToAdd As Byte())
Dim response As String = Nothing
Try
Dim requestUrl As String = "urlShop" & "/api/" & resource & "/" & id
MsgBox(requestUrl)
Dim webRequest As HttpWebRequest = DirectCast(System.Net.WebRequest.Create(requestUrl), HttpWebRequest)
webRequest.KeepAlive = True
webRequest.Credentials = New NetworkCredential(Me.LoginName, WebServicePrestashop._password)
webRequest.ContentLength = imageToAdd.Length
webRequest.Method = "POST"
webRequest.ContentType = "image/jpeg"
Dim boundary As String = "----" & DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture)
webRequest.ContentType = "multipart/form-data; boundary=" & boundary
Dim beginPostData = "--" & boundary & vbCrLf & "Content-Disposition: form-data; name=""image""; filename=""torrente.jpg""" & _
vbCrLf & "Content-Type: image/jpeg" & vbCrLf & vbCrLf
Dim boundaryBytes = System.Text.Encoding.ASCII.GetBytes(vbCrLf & "--" & boundary & "--" & vbCrLf)
Dim beginPostDataBytes = System.Text.Encoding.ASCII.GetBytes(beginPostData)
webRequest.ContentLength = beginPostData.Length + imageToAdd.Length + boundaryBytes.Length
' Get the request stream
Using dataStream As Stream = webRequest.GetRequestStream()
dataStream.Write(beginPostDataBytes, 0, beginPostDataBytes.Length)
dataStream.Write(imageToAdd, 0, imageToAdd.Length)
dataStream.Write(boundaryBytes, 0, boundaryBytes.Length)
End Using
' Get the response
Using webResponse As HttpWebResponse = DirectCast(webRequest.GetResponse(), HttpWebResponse)
If webResponse.StatusCode = HttpStatusCode.OK Then
Using reader As New StreamReader(webResponse.GetResponseStream())
response = reader.ReadToEnd()
MsgBox(response)
End Using
End If
End Using
Catch ex As WebException
MsgBox(ex.Message.ToString())
Dim reader As New StreamReader(ex.Response.GetResponseStream)
MsgBox(reader.ReadToEnd)
End Try
End Sub

Update a database from a .docx file

I have a HR web application which includes organization structure within workplaces.
The client is sending a .docx file with workplace name and its description. I need to make a C# application to get data from the .docx file and update some database tables with it.
I already tried .docx conversion to XML but I have no idea how to pick up data from that XML and insert it into the database.
Is there a easier way to update this database directly from a .docx file or what mechanics should I use to find data in the XML file.
Try this..
Below is the connection string to the database. You can modify it to suit yours
<connectionStrings>
<add name="conString" connectionString="Data Source=.\SQLEXPRESS;database=dbFiles; Integrated Security=true"/>
</connectionStrings >
To start with I have added a FileUpload control, a button and a Label to show messages
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="btnUpload" runat="server" Text="Upload"
OnClick="btnUpload_Click" />
<br />
<asp:Label ID="lblMessage" runat="server" Text=""
Font-Names = "Arial"></asp:Label>
And here is the snippet which is called on the Upload Button Click event
C#
protected void btnUpload_Click(object sender, EventArgs e)
{
// Read the file and convert it to Byte Array
string filePath = FileUpload1.PostedFile.FileName;
string filename = Path.GetFileName(filePath);
string ext = Path.GetExtension(filename);
string contenttype = String.Empty;
//Set the contenttype based on File Extension
switch(ext)
{
case ".doc":
contenttype = "application/vnd.ms-word";
break;
case ".docx":
contenttype = "application/vnd.ms-word";
break;
case ".xls":
contenttype = "application/vnd.ms-excel";
break;
case ".xlsx":
contenttype = "application/vnd.ms-excel";
break;
case ".jpg":
contenttype = "image/jpg";
break;
case ".png":
contenttype = "image/png";
break;
case ".gif":
contenttype = "image/gif";
break;
case ".pdf":
contenttype = "application/pdf";
break;
}
if (contenttype != String.Empty)
{
Stream fs = FileUpload1.PostedFile.InputStream;
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
//insert the file into database
string strQuery = "insert into tblFiles(Name, ContentType, Data)" +
" values (#Name, #ContentType, #Data)";
SqlCommand cmd = new SqlCommand(strQuery);
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = filename;
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value
= contenttype;
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes;
InsertUpdateData(cmd);
lblMessage.ForeColor = System.Drawing.Color.Green;
lblMessage.Text = "File Uploaded Successfully";
}
else
{
lblMessage.ForeColor = System.Drawing.Color.Red;
lblMessage.Text = "File format not recognised." +
" Upload Image/Word/PDF/Excel formats";
}
}
VB.Net
Protected Sub btnUpload_Click(ByVal sender As Object, ByVal e As EventArgs)
' Read the file and convert it to Byte Array
Dim filePath As String = FileUpload1.PostedFile.FileName
Dim filename As String = Path.GetFileName(filePath)
Dim ext As String = Path.GetExtension(filename)
Dim contenttype As String = String.Empty
'Set the contenttype based on File Extension
Select Case ext
Case ".doc"
contenttype = "application/vnd.ms-word"
Exit Select
Case ".docx"
contenttype = "application/vnd.ms-word"
Exit Select
Case ".xls"
contenttype = "application/vnd.ms-excel"
Exit Select
Case ".xlsx"
contenttype = "application/vnd.ms-excel"
Exit Select
Case ".jpg"
contenttype = "image/jpg"
Exit Select
Case ".png"
contenttype = "image/png"
Exit Select
Case ".gif"
contenttype = "image/gif"
Exit Select
Case ".pdf"
contenttype = "application/pdf"
Exit Select
End Select
If contenttype <> String.Empty Then
Dim fs As Stream = FileUpload1.PostedFile.InputStream
Dim br As New BinaryReader(fs)
Dim bytes As Byte() = br.ReadBytes(fs.Length)
'insert the file into database
Dim strQuery As String = "insert into tblFiles" _
& "(Name, ContentType, Data)" _
& " values (#Name, #ContentType, #Data)"
Dim cmd As New SqlCommand(strQuery)
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = filename
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value _
= contenttype
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes
InsertUpdateData(cmd)
lblMessage.ForeColor = System.Drawing.Color.Green
lblMessage.Text = "File Uploaded Successfully"
Else
lblMessage.ForeColor = System.Drawing.Color.Red
lblMessage.Text = "File format not recognised." _
& " Upload Image/Word/PDF/Excel formats"
End If
End Sub
The above code simply reads the uploaded File as Stream and then converts the Stream to Byte array using Binary Reader and then the finally the byte arrays is saved to the database InsertUpdateData method executes the query to save the data in database
The InsertUpdateData function is given below
C#
private Boolean InsertUpdateData(SqlCommand cmd)
{
String strConnString = System.Configuration.ConfigurationManager
.ConnectionStrings["conString"].ConnectionString;
SqlConnection con = new SqlConnection(strConnString);
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
try
{
con.Open();
cmd.ExecuteNonQuery();
return true;
}
catch (Exception ex)
{
Response.Write(ex.Message);
return false;
}
finally
{
con.Close();
con.Dispose();
}
}

Uploading Image MultiPart Form HTTPWebRequest - Getting Image Data To String?

I am trying to upload a multi-part form with HTTPWebRequest & all is ok until I added an image to upload, mainly I am trying to do exactly the same request as a browser makes which looks like this:
-----------------------------41184676334
Content-Disposition: form-data; name="file"; filename="guitar tape.jpg"
Content-Type: image/jpeg
IMAGEDATAHERE
-----------------------------41184676334
Content-Disposition: form-data; name="save"
save
-----------------------------41184676334--
I am lost on how to format / read the image to set it into the request that I am making below:
Dim boundary As String = "-----------------------------" & DateTime.Now.Ticks.ToString("x")
Dim req As HttpWebRequest = DirectCast(WebRequest.Create("http://www.mysite.com/upload.php"), HttpWebRequest)
req.Method = "POST"
req.ContentType = "multipart/form-data; boundary=" & "---------------------------" & DateTime.Now.Ticks.ToString("x")
req.KeepAlive = False
Dim builder As New StringBuilder()
builder.Append(boundary & vbCrLf & "Content-Disposition: form-data; name=""variable1""" & vbCrLf & vbCrLf & "1" & vbCrLf)
builder.Append(boundary & vbCrLf & "Content-Disposition: form-data; name=""file""; filename=""" & FileName & """" & vbCrLf)
builder.Append("Content-Type: application/octet-stream")
builder.Append(vbCrLf & vbCrLf)
' Add Photo Here
If UpdateImage = True Then
' Load Image
Dim ImageData As System.Drawing.Image
Dim fs As New System.IO.FileStream(ImagePath, System.IO.FileMode.Open)
ImageData = Image.FromStream(fs)
fs.Close()
' Add Image To Header
builder.Append(ImageData)
builder.Append(vbCrLf)
Else
builder.Append(vbCrLf)
End If
builder.Append(boundary & vbCrLf & "Content-Disposition: form-data; name=""save""" & vbCrLf & vbCrLf & "save")
' Footer Bytes
Dim close As Byte() = Encoding.UTF8.GetBytes("--")
Dim postHeader As String = builder.ToString()
Dim postHeaderBytes As Byte() = Encoding.UTF8.GetBytes(postHeader)
Dim boundaryBytes As Byte() = Encoding.ASCII.GetBytes(vbCrLf & boundary & "--" & vbCrLf)
Dim length As Long = postHeaderBytes.Length + boundaryBytes.Length
req.ContentLength = length
Dim requestStream As Stream = req.GetRequestStream()
Dim fulllength As Integer = postHeaderBytes.Length + boundaryBytes.Length
' Write out our post header
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length)
' Write out the trailing boundary
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length)
Dim responce As WebResponse
responce = req.GetResponse()
requestStream.Close()
Dim s As Stream = responce.GetResponseStream()
Dim sr As New StreamReader(s)
Dim Content As String = sr.ReadToEnd()
At the moment it is simply posting "System.Drawing.Bitmap" as the image data but I am not sure how to get the same raw data for the image that looks like this:
J©õݨe‚Lnž¿Ëã/ǧúÐ5ý¼C÷Cý>ß’t;fm—=Äw:�/E±ËÙÏ$á#%Pc>× Šgw.²Ab“:ÅÓù:ϯÌh6à€Z§Ó‚g£®hÚD6¨Ø^Ú2ô`ä¨L�YÆÄÅCX#I“ÈÌãj¦L˜•’|¥�Eb¡ëQ–¤Ú, 3\UzL  öÔoj4�•±’u«c¼#„oÕ`îF>·o—ŠûÅ«ÎÑ™¶Ç˜ýº*i°œÈVŒ�Qû”Ñ[.�ÔmçE•ì¦eNCh�Ù
é§�É$m¿ôš"»ÌNæ(VÌmp›F¹XÈ88™ªüµ…d•XµÔÜ#�ˆŠv‘º‚F‚§Yûb
Any ideas on how I could do this or would I need to change my methods?
builder.Append(ImageData)
is not correct. you need read the image as byte, then add the byte[] to the multipart post.
see details at Using HttpWebRequest to POST data/upload image using multipart/form-data
and make sure use a http sniffer (i.e. fiddler) to see what it is actually sending.
first, load image into byte array, then convert it to base64:
imgBase64 = Convert.ToBase64String(my_image_byte_array)
My "OpenFileDialog" name is "file". When a "button" is clicked it will show a pop up dialog for selecting jpg, jpeg, png image files, it can also add bmp or any image file type. Then after the selection of a image file it will show on "PictureBox" i name it as "picboxProfileID".
In Visual Basic:
file.Filter = "image file (*.jpg, *.jpeg, *.png) | *.jpg; *.jpeg; *.png | all files (*.*) | *.*"
If (file.ShowDialog <> Windows.Forms.DialogResult.Cancel) Then
picboxProfileID.Image = Image.FromFile(file.FileName)
picboxProfileID.ImageLocation = file.FileName
txtName.Text = file.FileName
My.Computer.Network.UploadFile(file.FileName, "http://localhost/VTVTS/uploadImageSample.php")
Else
picboxProfileID.Image = Nothing
End If
The destination of the file uploaded will be uploaded on the "images/" of the parent folder php file created.
In PHP:
<?php
$response = array();
$image = $_FILES['file'];
$imageName = $image['name'];
$imageTmpName = $image['tmp_name'];
$imageSize = $image['size'];
$imageError = $image['error'];
$imageType = $image['type'];
$fileExt = explode('.', $imageName);
$fileActualExt = strtolower(end($fileExt));
$allowed = array('jpg', 'jpeg', 'png');
if(in_array($fileActualExt, $allowed)){
$fileNameNew = uniqid('', true).".".$fileActualExt;
$fileDestination = 'images/'.$fileNameNew;
$newDestination = move_uploaded_file($imageTmpName, $fileDestination);
$response['error'] = false;
$response['message'] = "Upload Image Successful";
}else{
$response['error'] = true;
$response['message'] = "You cannot upload files of this type!";
}
echo json_encode($response);
Happy Coding!