I tried to implement the WebSocket Protocol and connecting a JavaScript WebSocket with a Java WebSocket Server.
The JavaScript part is pretty straight forward and works as expected.
I wrote the Java server myself and read the rfc 6455 page 7 for the correct handshake response. So the server generates the correct response and sends it. I wrote a Java client dummy to make sure it gets send.
But the problem is that the JavaScript / Browser seems not to receive the handshake response and kills the request after some seconds (but does not close the tcp socket).
Here is the handshake:
Client
GET / HTTP/1.1
Host: 127.0.0.1:4455
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://localhost
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Server
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
HTML JavaScript
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Socket testing - Client</title>
</head>
<body>
<div id="container"></div>
<script type="text/javascript">
var socket = new WebSocket('ws://127.0.0.1:4455');
socket.addEventListener("error",function(e){
console.log("an error ocurred: ",e)
})
socket.addEventListener("close",function(e){
console.log("the connection was closed: ",e)
})
socket.addEventListener("open",function(e){
console.log("the connection was opened: ",e)
})
socket.addEventListener("message",function(e){
console.log("recieved a message: ",e)
})
</script>
</body>
</html>
Java (excerpt)
public class SocketHandlerWebSocketLevel extends SocketHandler {
private HashMap<String, String> connectionHeaders;
private InputStreamReader stringReader;
private OutputStreamWriter stringWriter;
public SocketHandlerWebSocketLevel(Socket socket) {
super(socket);
connectionHeaders = new HashMap<String, String>();
try {
stringReader = new InputStreamReader(s.getInputStream());
} catch (IOException e) {
e.printStackTrace();
close();
print("could not get the input stream");
return;
}
try {
stringWriter = new OutputStreamWriter(s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
close();
print("could not get the output stream");
return;
}
}
#Override
public void run() {
print("Started handler");
char b;
String buffer = "";
try {
mainLoop: while (true) {
while (stringReader.ready() || buffer.length() == 0) {
if ((b = (char) stringReader.read()) != -1) {
buffer += b;
} else {
break mainLoop;
}
}
gotMessage(buffer);
buffer = "";
}
} catch (IOException e) {
close();
print("connection was killed remotly, could not read the next byte");
return;
}
close();
print("connection was closed remotely, stopped Handler, closed socked");
}
private void gotMessage(String message) {
if (connectionHeaders.size() == 0) {
connectionHeaders = parseHttpHeader(message);
handshakeResponse();
} else {
print(message);
}
}
private void handshakeResponse() {
/*
taken from: https://www.rfc-editor.org/rfc/rfc6455#page-7
For this header field, the server has to take the value (as present
in the header field, e.g., the base64-encoded [RFC4648] version minus
any leading and trailing whitespace) and concatenate this with the
Globally Unique Identifier (GUID, [RFC4122]) "258EAFA5-E914-47DA-
95CA-C5AB0DC85B11" in string form, which is unlikely to be used by
network endpoints that do not understand the WebSocket Protocol. A
SHA-1 hash (160 bits) [FIPS.180-3], base64-encoded (see Section 4 of
[RFC4648]), of this concatenation is then returned in the server's
handshake.
Concretely, if as in the example above, the |Sec-WebSocket-Key|
header field had the value "dGhlIHNhbXBsZSBub25jZQ==", the server
would concatenate the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
to form the string "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-
C5AB0DC85B11". The server would then take the SHA-1 hash of this,
giving the value 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6
0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. This value is
then base64-encoded (see Section 4 of [RFC4648]), to give the value
"s3pPLMBiTxaQ9kYGzzhZRbK+xOo=". This value would then be echoed in
the |Sec-WebSocket-Accept| header field.
*/
String secWebSocketKey, secWebSocketAccept, GUID, template, merged, toSend;
secWebSocketKey = connectionHeaders.get("Sec-WebSocket-Key");
GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
template = "HTTP/1.1 101 Switching Protocols\nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Accept: %s\nSec-WebSocket-Protocol: chat\n";
// combine secWebSocketKey and the GUID
merged = secWebSocketKey + GUID;
print("merged: " + merged);
// convert to byte[]
byte[] asBytes = merged.getBytes();
print("asBytes: " + Arrays.toString(asBytes));
// SHA-1 hash
byte[] sha1 = SHA1Hash(asBytes);
print("sha1: " + Arrays.toString(sha1));
// base64 encode
byte[] base64 = base64Encode(sha1);
print("base64: " + Arrays.toString(base64));
// reconvert to string to put it into the template
secWebSocketAccept = new String(base64);
toSend = String.format(template, secWebSocketAccept);
print(toSend);
try {
stringWriter.write(toSend, 0, toSend.length());
stringWriter.flush();
} catch (IOException e) {
print("hanshake sending failed!");
}
}
private HashMap<String, String> parseHttpHeader(String h) {
HashMap<String, String> fields = new HashMap<String, String>();
String[] rows = h.split("\n");
if (rows.length > 1) {
fields.put("Prototcol", rows[0]);
Pattern pattern = Pattern.compile("^([^:]+): (.+)$");
for (int i = 1; i < rows.length; i++) {
Matcher matcher = pattern.matcher(rows[i]);
while (matcher.find()) {
if (matcher.groupCount() == 2) {
fields.put(matcher.group(1), matcher.group(2));
}
}
}
}
return fields;
}
private byte[] SHA1Hash(byte[] bytes) {
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
return null;
}
md.update(bytes);
return md.digest();
}
private byte[] base64Encode(byte[] bytes) {
byte[] encodedBytes = Base64.getEncoder().encode(bytes);
return encodedBytes;
}
Where might be my error? What could be missing, maybe a "message end" symbol?
Note that I don't want to use a framework.
The solution was simple. I just used Wireshark to debug this whole thing: I just forgot the carriage return.
The correct string in the Java class would be:
template = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
Until this modification the browser is not able to interpret it as HTTP data in the TCP package.
Related
Since DeepL updated their API which also their website (https://www.deepl.com/translator) uses, an error appears when you're requesting a translation via Java or Python. It says "Too many requests." A year ago the answer here (Using DeepL API to translate text) from EmilioK worked.
Because of their update, the API URL changed to "https://www2.deepl.com/jsonrpc". But the response is {"jsonrpc": "2.0","error":{"code":1042901,"message":"Too many requests."}}. Translating via the website works, so they seem to have implemented a background check. I already tried to debug their JavaScript code, but I don't understand what I'm doing wrong. At last I tried to re-build the requests by analysing the network traffic from the homepage. Didn't work either.
Besides, it seems like others are having the same problem (https://github.com/EmilioK97/pydeepl/issues/12, https://github.com/vsetka/deepl-translator/issues/9).
I used Java 8 with the Apache HttpClient 4.5.8:
private static final String BASE_URL = "https://www2.deepl.com/jsonrpc";
private static AtomicInteger requestId = new AtomicInteger(10000 * (int) Math.round(10000 * Math.random()));
private static final CloseableHttpClient HTTP_CLIENT = HttpClients.createDefault();
public void example() {
HttpResponse httpResponse = HTTP_CLIENT.execute(generateRequest("Hello", "EN", "DE"), getContext());
JSONObject response = new JSONObject(EntityUtils.toString(httpResponse.getEntity()));
System.out.println(response.toString());
}
HttpContext getContext() {
CookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("LMTBID", "3389513b-e369-4810-a2f3-73b9405e0b0d|403992a1240e1eca6c6e98b428849a3c");
cookie.setDomain(".deepl.com");
cookie.setPath("/");
cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true");
cookieStore.addCookie(cookie);
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);
return localContext;
}
HttpPost generateRequest(String text, String from, String to) {
HttpPost request = new HttpPost(BASE_URL);
StringEntity params = new StringEntity(getJsonRequest(text, from, to).toString(), StandardCharsets.UTF_8);
request.addHeader(HttpHeaders.HOST, "www2.deepl.com");
request.addHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0");
request.addHeader(HttpHeaders.ACCEPT, "*/*");
request.addHeader(HttpHeaders.ACCEPT_LANGUAGE, "de,en-US;q=0.7,en;q=0.3");
request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, deflate, br");
request.addHeader(HttpHeaders.REFERER, "https://www.deepl.com/translator");
request.addHeader(HttpHeaders.CONTENT_TYPE, "text/plain");
request.addHeader(HttpHeaders.CONNECTION, "keep-alive");
request.addHeader("X-Requested-With", "XMLHttpRequest");
request.addHeader("Origin", "https://www.deepl.com");
request.addHeader("DNT", "1");
request.addHeader("TE", "Trailers");
request.setEntity(params);
request.setConfig(requestConfig);
return request;
}
private static JSONObject getJsonRequest(String text, String from, String to) {
JSONObject send = new JSONObject();
send.put("id", requestId.incrementAndGet());
send.put("jsonrpc", "2.0");
send.put("method", "LMT_handle_jobs");
JSONObject paramsObject = new JSONObject();
JSONArray jobsArray = new JSONArray();
JSONObject jobsObject = new JSONObject();
jobsObject.put("kind", "default");
jobsObject.put("quality", "fast");
jobsObject.put("raw_en_context_after", new JSONArray());
jobsObject.put("raw_en_context_before", new JSONArray());
jobsObject.put("raw_en_sentence", text);
jobsArray.put(jobsObject);
JSONObject langObject = new JSONObject();
JSONArray userPreferredLangsArray = new JSONArray();
userPreferredLangsArray.put(to);
userPreferredLangsArray.put(from);
langObject.put("source_lang_user_selected", from.getLanguageCode());
langObject.put("target_lang", to);
langObject.put("user_preferred_langs", userPreferredLangsArray);
paramsObject.put("jobs", jobsArray);
paramsObject.put("lang", langObject);
paramsObject.put("priority", -1);
paramsObject.put("timestamp", System.currentTimeMillis());
send.put("params", paramsObject);
return send;
}
The result should look like this, but I don't remember exactly:
{"result":{"source_lang":"EN","target_lang":"DE","translations":[{"beams":[{"postprocessed_sentence":"Hallo","score":0.5,"totalLogProb":0.3,"num_symbols":1},{"postprocessed_sentence":"Guten Tag","score":0.3,"totalLogProb":0.7,"num_symbols":2}]}]}}
I can't tell the length of the text items you are trying to translate, but I had to send in groups of text of max 1000 at a time. Also I have a subscription and not using the free side.
In my application I am connecting chrome extension with windows application using websocket,
Javascript code :
var socket = new WebSocket('ws://172.xx.xxx.xx:11223/');
socket.onopen = function(event)
{
// Web Socket is connected, send data using send()
socket.send("hi..");
};
And C# code :
public static TcpListener Weblistener = null;
public static int selWebSocketPort = 0;
public static void StartListeningSahi()
{
Weblistener = new TcpListener(IPAddress.Parse(ipAddStr), portNumForSelenium);
try{
Weblistener.Start();
int TestingCycle = 100;
// Start listening for connections.
while (TestingCycle > 0){
TcpClient handler = Weblistener.AcceptTcpClient();
// An incoming connection needs to be processed.
lock (ClientSockets.SyncRoot){
if (handler != null){
int i = ClientSockets.Add(new ClientHandler(handler));
((ClientHandler)ClientSockets[i]).Start();
SelWebSocketPort = (handler.Client.RemoteEndPoint as IPEndPoint).Port;
NetworkStream networkStream = handler.GetStream();
Byte[] clientReq = new Byte[handler.Available];
networkStream.Read(clientReq, 0, clientReq.Length);
string headerRequest = Encoding.UTF8.GetString(clientReq);
SendResponseToWebSocket(handler, networkStream, headerRequest);
}
else
continue;
}
}
Weblistener.Stop();
}
catch (Exception e){
Console.WriteLine(e.ToString());
}
}
public static void SendResponseToWebSocket(TcpClient handler, NetworkStream networkStream, string headerRequest)
{
// generate accept key fromm client header request
var key = headerRequest.Replace("ey:", "`")
.Split('`')[1]
.Replace("\r", "").Split('\n')[0]
.Trim();
var responseKey = AcceptKey(ref key);
//create the response for the webclient
var newLine = "\r\n";
var response = "HTTP/1.1 101 Switching Protocols" + newLine
+ "Upgrade: websocket" + newLine
+ "Connection: Upgrade" + newLine
+ "Sec-WebSocket-Accept: " + responseKey + newLine + newLine;
//send respose to the webclient
Byte[] sendBytes = Encoding.ASCII.GetBytes(response);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
selWebSocketPort = (handler.Client.RemoteEndPoint as IPEndPoint).Port;
}
This is working fine for http site. But after that I changed the this javascript line var socket = new WebSocket('ws://172.xx.xxx.xx:11223/'); to var socket = new WebSocket('wss://172.xx.xxx.xx:11223/'); to support https sites, but unable to do so. I am getting below error on chrome -
WebSocket connection to 'wss://172.16.106.22:11223/' failed: WebSocket opening handshake timed out
The handshaking is getting failed as in the request header I am getting some junk value.
Am I missing something ?
I have a controller, which is used to flush the bytes, which inturn will generate the PDF on the client side. But, if an exception occurs, I want to catch that and show some appropriate message to the user.
I tried Ajax, but Ajax uses only JSON, String or XML for message exchange format. How can I handle this conditon?
I have to generate the pdf in success case or catch the exception. Here is my controller and javascript code
try {
MyUtil.generatePdf(response, documentBytes, "DU"); // --> This method will flush the bytes
} catch (Exception e) {
result.setStatus("EXCEPTION OCCURED.");
}
return result;
Generate pdf method
public static void GeneratePdf(HttpServletResponse response, byte[] documentBytes,
String fileName) {
response.setHeader("Content-Disposition", "inline;filename=" + fileName + ".pdf");
response.setContentType("application/pdf");
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, postcheck=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentLength(documentBytes.length);
ServletOutputStream out = null;
try {
out = response.getOutputStream();
out.write(documentBytes);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Javascript code
try {
window.open("http://localhost:8080/INQ/CBU/5559901410151HELMPFN");
} catch (e) {
console.log(e);
}
I do not think that you can do this with window.open().
My suggestion is to use servlet API in a way that you either download the PDF or in case of an error show an error page to the user.
I have some test code for exactly the scenario in which either the PDF is written out OR an error page is sent to the user with an error message.
The clue is that an exception is caught and in that case an error message is sent out to the user using a different encoding.
servlet code
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
#WebServlet("/download")
public class PDFServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String fileName = "asset_report1.pdf"; // Dummy file
// This throws sometimes an exception.
byte[] documentBytes = MyUtil.generatePdf(fileName);
response.setHeader("Content-Disposition", "inline;filename=" + fileName);
response.setContentType("application/pdf");
expireCache(response);
response.setHeader("Pragma", "public");
response.setContentLength(documentBytes.length);
ServletOutputStream out = response.getOutputStream();
out.write(documentBytes);
out.flush();
} catch (IOException e) {
expireCache(response);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"The PDF file could not be retrieved.");
}
}
private void expireCache(HttpServletResponse response) {
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, postcheck=0, pre-check=0");
}
}
This works out pretty well. Either you get the PDF downloaded OR you get an error page. You will need to eventually work on you error page to make it look pretty, but the default error page is a start.
Sometimes you see the PDF and in case of an error the default error page:
In your case its best to get the pdf response as arraybuffer in angular side and store it as a blob and then download it. You can do it making a post rquest to the server. And add a error block in your angular code.
Server Side Code..
List<PhysicalCountEntityTo> salaryList = exportNonDashBoardReportManager.fetchSalaryDetails(payloadBean);
HashMap<String, Object> parametersPDF = new HashMap<String, Object>();
JasperPrint jasperPrint = null;
JRBeanCollectionDataSource beanCollectionDataSource = null;
beanCollectionDataSource = new JRBeanCollectionDataSource(salaryList);
String reportPath = httpServletRequest.getServletContext().getRealPath("//WEB-INF//JasperReports//Salary.jasper");
jasperPrint = JasperFillManager.fillReport(reportPath, parametersPDF, beanCollectionDataSource);
httpServletResponse.addHeader("Content-disposition","attachment; filename=Salary.pdf");
ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();
JasperExportManager.exportReportToPdfStream(jasperPrint, servletOutputStream);
Angular Side Code -- you can use this code under your ajax request as you're using javascript
exportPDF(event){
this.showPageSpinner=true;
this.httpRestClient.fetchPDF("download_salary_report", this.payloadBean).subscribe(
response => {
var blob = new Blob([response], {type: 'application/pdf'});
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE');
var trident = ua.indexOf('Trident/');
var edge = ua.indexOf('Edge/');
if(msie > 0 || trident > 0 || edge > 0){
window.navigator.msSaveOrOpenBlob(blob,'Salary.pdf');
}
else if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
var link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = "Salary.pdf";
document.body.appendChild(link);
link.click();
window.setTimeout(function() {
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
}, 0);
}
else{
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="Salary.pdf";
link.click();
}
this.showPageSpinner=false;
},
error=>{
// show your message here
});
}
Important - In request header add response type to 'arraybuffer' as 'json' otherwise it won't work
fetchPDF(url: string,data): Observable<any> {
this.getCredentials();
const authHeaders = this.createBasicAuthorizationHeader(this.credentials);
return this.http.post(this.getApiUrl(url),data,{headers: authHeaders,'responseType' : 'arraybuffer' as 'json'})
}
It works in IE,Mozilla and Crome..
This is my very first question I am posting on StackOverflow. I usually tend to find answers to any question I have for whatever project, but I am really stuck on this one. I'm writing a Chrome extension that attempts to send JSON-objects over a HTTP post request with certain data in it to a basic Java server that will -in a later stage- process some of the data and return a HTTP response with relevant (processed) information for the client. This is the relevant JavaScript snippet on client-side:
function postRequest(jsonObject) {
var param = JSON.stringify(jsonObject);
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4) {
console.log(request.response);
}
};
request.open("POST", "http://"+link);
request.setRequestHeader("Content-type","text/plain");
request.send(param);
// request.abort();
}
The input JSON-object is legit and the link-item is the predefined host IP of the server. The server-side code is Java-based and is the following:
public class Server {
public static void main(String args[]) throws Exception {
while (true) {
try {
ServerSocket ss = new ServerSocket(1024);
Socket s = ss.accept();
System.out.println("Request: ");
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw = new PrintWriter(s.getOutputStream());
String line;
while ((line = br.readLine()) != null) {
if (line.length() == 0) {
break;
}
System.out.print(line + "\r\n");
}
System.out.println("");
System.out.println("Response:");
String response = "HTTP/1.1 200 OK \r\n" + "Access-Control-Allow-Origin: * \r\n"
+ "Connection: close \r\n" + "\r\n";
System.out.println(response);
pw.write(response);
while ((line = br.readLine()) != null) {
if (line.length() == 0) {
break;
}
System.out.print(line + "\r\n");
}
br.close();
pw.close();
System.out.println("");
System.out.println("Socket Closed");
System.out.println("");
s.close();
ss.close();
} catch (Exception ex) {
// Do whatever
}
}
}}
The server does receive the request and the JSON-object, but no response is received on client side (readyState is usually 4, but status code is 0 and responseText is empty). Additionally the connection is not closed when I don't use request.abort() or close the extension's window. It for sure has nothing to do with the permissions in the manifest file, so I didn't include it in this post. Can somebody see what my mistake is or anybody have had a similar experience?
EDIT:
The HTTP request is received on server side and looks like:
POST / HTTP/1.1
Host: [IP address of the server; I deleted the exact address for privacy]
Connection: keep-alive
Content-Length: 173
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
Origin: chrome-extension://nhpingbdjkkljheamibjobneeehiednk
Content-type: text/plain
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4,fr;q=0.2
Since the request is received on server side, I figured that the actual sending of the response is currently unsuccessful. Might it have something to do with the origin domain of the client? When I copy-paste that domain in my browser, I get a ERR_FILE_NOT_FOUND.
How to receive angular $http post multipart form data from Grails. Here I have sent multipart form data from Angular controller to the Grails. I am new to Grails.
Anyone can give me guidance to retrieve-boundary data. I don't Know exactly it's correct form to receive image file data with some input data also.
Request headers in browser's network console:
Provisional headers are shown
Accept:application/json, text/plain, */*
Content-Type:multipart/form-data; boundary=----
WebKitFormBoundary0p6R8BecvYqzcbMK
Origin:file://
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us)
AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53
Request Payload
------WebKitFormBoundary0p6R8BecvYqzcbMK
Content-Disposition: form-data; name="rackImage"; filename="PhoneGap.png"
Content-Type: image/png
------WebKitFormBoundary0p6R8BecvYqzcbMK
Content-Disposition: form-data; name="storeNo"
HD1304
------WebKitFormBoundary0p6R8BecvYqzcbMK
Content-Disposition: form-data; name="rackQty"
12
------WebKitFormBoundary0p6R8BecvYqzcbMK--
Here you go. Just write the following in your controller:
class MyController {
def upload() {
def multipartFile = params.rackImage
InputStream is
FileOutputStream fos
byte[] fileRead = new byte[1024]
File tempFile
try {
is = multipartFile.getInputStream()
String fileName = multipartFile.getOriginalFilename()
String path = "./"
fileName = fileName.replaceAll("[^a-zA-Z0-9//._-]+", "").toLowerCase()
tempFile = new File(path + "" + fileName)
fos = new FileOutputStream(tempFile);
int i = is.read(fileRead)
while (i != -1) {
fos.write(fileRead, 0, i);
i = is.read(fileRead);
}
} catch (FileNotFoundException e) {
log.error "Exception uploading", e
} catch (IOException e) {
log.error "Exception uploading", e
} finally {
fos?.close()
is?.close()
}
// Now access the File: "tempFile"
}
}