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?