How to receive Angular $http post multipart form data in Grails - javascript

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"
}
}

Related

Body of POST request from javascript application in browser using XMLHttpRequest is empty when arriving at the server

I have two applications: one web client and one java server. The web client sends an HTTP POST request with a JSON body of data, and the server should receive the data and display it on the screen. The problem is that when the server reads the body of the request, there is nothing to read. What is wrong?
Edit: I realized that the problem is on the browser side (since I could send and read an HTTP POST request from some other website), but I still don't know what the problem is. Is this related to the browser running the code? When I use Chrome I get the described problem. When I use Firefox or IE the java server isn't even notified; it doesn't even run the handle method that is supposed to run when it gets an HTTP request.
It worked to read data at the server when I coded the content type as url encoded. I think it was: x-www-form-urlencoded. But I want to send data as JSON.
I use XMLHttpRequest for the web client, as you can see below.The web client:
<!DOCTYPE html>
<html>
<body>
<script>
function handleInput(){
var title = "title";
var reviewer = "reviewer";
const xhr = new XMLHttpRequest();
var searchInfo = {
title:title,
reviewer:reviewer
};
xhr.open('POST', 'http://localhost:8001');
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.send(JSON.stringify(searchInfo));
}
</script>
</body>
</html
The server:
import java.io.IOException;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class Server {
public static void main(String[] args) {
try {
HttpServer server = HttpServer.create(new InetSocketAddress("localhost", 8001), 0);
HttpHandler handler = new MyHttpHandler();
HttpContext context = server.createContext("/");
context.setHandler(handler);
server.start();
System.out.println("Server started on port 8001");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
The servers HTTP handler:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
public class MyHttpHandler implements HttpHandler {
#Override
public void handle(HttpExchange httpExchange) throws IOException {
InputStream is = httpExchange.getRequestBody();
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) { br.readLine is always null!!!
content.append(line);
content.append("\n");
}
System.out.println("Content: " + content.toString());
}
}
As your server (java side, live in localhost:8001) and client (xhttp side, live in somewhere else) are separated. The request is considered as cross origin requests (CORs).
There are 2 types of cross origin requests - Safe and unsafe:
Only the below Content-Type are considered as SAFE in cross site request:
application/x-www-form-urlencoded
multipart/form-data
text/plain
So, application/json; is considered UNSAFE.
For safe request, there is not much restriction on server so you can get the response back while using application/x-www-form-urlencoded
client <=> POST request <=> Server
For unsafe request, there is a preflight request (a special OPTIONS action) to ask the server
if client origin is allowed and
what can the client do
before making the real request, in your case the POST request.
client <=> pre-flight (OPTIONS) request <=> Server
client <=> POST request <=> Server
So the problem is there is no handling of preflight request and the request cannot be processed by server.
To deal with it, you need to change your handler as follow:
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
public class MyHttpHandler implements HttpHandler {
#Override
public void handle(HttpExchange httpExchange) throws IOException {
Headers headers = httpExchange.getResponseHeaders();
System.out.println(httpExchange.getRequestMethod());
headers.add("Access-Control-Allow-Origin", "*"); // * means allow all origin, in production, it should be the origin you trust e.g. http://client.abc.com
if (httpExchange.getRequestMethod().equalsIgnoreCase("OPTIONS")) {
headers.add("Access-Control-Allow-Headers", "Content-Type"); // allow clients to pass in content-type
headers.add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
httpExchange.sendResponseHeaders(204, -1);
return;
}
InputStream is = httpExchange.getRequestBody();
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) { // br.readLine is always null!!!
content.append(line);
content.append("\n");
}
System.out.println("Content: " + content.toString());
// added response as well to complete the request
String response = "Good" ;
httpExchange.sendResponseHeaders(200, response.length());
OutputStream os = httpExchange.getResponseBody();
os.write(response.getBytes(StandardCharsets.UTF_8));
os.close();
httpExchange.close();
}
}
HTML
<!DOCTYPE html>
<html>
<body>
<button onclick="handleInput()">Click</button>
<script>
function handleInput() {
var title = "title";
var reviewer = "reviewer";
const xhr = new XMLHttpRequest();
xhr.onload = function() {
console.log('done')
}
var searchInfo = {
title: title,
reviewer: reviewer,
};
xhr.open("POST", "http://localhost:8001");
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xhr.send(JSON.stringify(searchInfo));
}
</script>
</body>
</html>
To further understanding CORs:
https://javascript.info/fetch-crossorigin
For your html
<form name="searchForm" id="searchForm" onSubmit="handleInput(event)">
...
</form>
<script>
function handleInput(e){
e.preventDefault()
...
}
</script>

Catch exception from controller in Window.open using Javascript

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..

No HTTP response from Chrome extension to my Java Server

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.

Handshake between JS WebSocket and Java

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.

Webaudio API: store arraybuffer on server as file and retrieve it later?

I'm desperately trying to find a solution to my problem.
CONTEXT: web application managing audio through WebAudio API; JavaScript+jQuery client side; PHP5 server side.
(Sorry I had to chop off part of the code below to keep this post short and readable)
1) I have an arraybuffer object read locally with a filereader obj, and stored locally in a vis.js dataset (that's what does essnetially) as follow...
var reader = new FileReader();
reader.onload = function(ev) {
//this store the content into an "audiodata" property of an item part of a vis.js dataset whose name is "clips"
songModule.createNewClip({ arrayBufferObj:ev.target.result })
};
reader.readAsArrayBuffer(file);
IMPORTANT: At this stage this object is also passed to a audioContext.decodeAudioData (arrayBufferObj, function (buffer) {..} THAt WORKS Correctly AND GIVE THE RIGHT OUTPUT
.. So far so good..
2) I upload the object to the server as follow:
var formData = new FormData(document.getElementById("temporaryForm"))
...
formData.append('audiodata', clips.get(localClipId).audiodata)
$.ajax({
type: 'POST',
url: 'addUpdateClip.php',
data: formData ,
//dataType: 'json',
processData: false, //It’s imperative that you set the contentType option to false, forcing jQuery not to add a Content-Type header for you
contentType: false,
cache: false,
...
)}
3) PHP page addUpdateClip.php retrieve and store to a file on the server data:
... $myfile = fopen($uniqueFileName, "w");
if (!fwrite($myfile, getValueFromPostOrGet('audiodata'))) //=$_POST["audiodata"]
fclose($myfile);
File seems to be correctly written on server
4)..But... Retreiving later directly the generated file on server and passing to the
audioContext.decodeAudioData function cause an error "Uncaught SyntaxError: Failed to execute 'decodeAudioData' on 'AudioContext': invalid ArrayBuffer for audioData.". Below the last version of my experiments.
var xhr = new XMLHttpRequest();
xhr.open('GET', Args.filename , true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var responseArrayBuffer=xhr.response
if (responseArrayBuffer){
var binary_string = ''
bytes = new Uint8Array(xhr.response);
for (var i = 0; i < bytes.byteLength; i++) {
binary_string += String.fromCharCode(bytes[i]);
}
base64_string = window.btoa(binary_string);
console.log(base64_string)
//var blob = new Blob([responseArrayBuffer], {type: "audio/wav"});
songModule.clipAudioDataReceived(newId, blob, Args.waveformDataURL )
}
}
xhr.onreadystatechange=function(){console.log(xhr.readyState,xhr.status, xhr.responseText )}
};
xhr.send();
Any clue?
___________To reply to noththeup:___________________
Request URL:http://XXXXXXX/addUpdateClip.php
Request Method:POST
Status Code:200 OK
Accept:`*/*`
Accept-Encoding:gzip,deflate
Accept-Language:it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4,en-GB;q=0.2,fr;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Content-Length:43324
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryaWagMNKe8hprn1pI
Cookie:PHPSESSID=m3okfanf1isbstueih9qq3k6r3
Host:onlinedaw
Origin:http://xxxxxxxxx
Pragma:no-cache
Referer:http://xxxxxxxxx/editSong.php?song_id=9
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payload
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="mode"
add
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="id"
7961f2b6-92cd-be59-f7a7-5c59f1c69fc5
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="song_id"
9
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="group"
13
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="start"
2010-01-01 00:02:58
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="startMs"
748
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="clipDurationMs"
8617
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="audiodata"
[object ArrayBuffer]
------WebKitFormBoundaryaWagMNKe8hprn1pI
Content-Disposition: form-data; name="extension"
wav
Do you see anything strange?
Answer posted by the OP in the question:
I kept on using the same wave file to test, hence file on the server were always the same size(11 bytes). This way I didn't realized that the client NEVER sent the data meant to be cast, but the string "aray buffer".
After further digging I noticed that any time I tried to store the array buffer into the dataset form vis.js it was turned into its description: the string "array buffer", which is indeed 11 bytes !
Solution: simply, according to me, the vis.js dataset is not suitable to contain array buffer. I used a parallel JavaScript array instead, and it worked.

Categories