I want to split a file to blob and upload them to server. I use File.slice() to split file.Then I save these blobs to an array.When i send these blobs to the server, server received files.But the browser prompt an error:
Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'.
Here is my codes.
//html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file" name="enfile" id="enfile">
<button id="btn">Add</button>
<script>
// ./upload/BlobUpload.do
var btn = document.querySelector('#btn');
btn.onclick = function() {
var src = document.querySelector('#enfile');
var file = src.files[0];
var chunk = 1024 * 100;
var chunks = [];
var start = 0;
var j = 0;
for (var i = 0; i < Math.ceil(file.size / chunk); i++) {
var end = start + chunk;
chunks[i++] = file.slice(start, end);
start = end;
j++;
}
var xhr = new XMLHttpRequest();
xhr.open('post', './upload/BlobUpload.do', true);
for (let i = 0; i < chunks.length; i++) {
var fname = file.name;
var size = file.size;
var formData = new FormData();
formData.append('regularName', fname);
formData.append('size', size);
formData.append('total', j);
formData.append('offset', i * chunk);
formData.append('current', i);
formData.append('data', chunks[i], 'data');
xhr.send(formData);
}
}
var disableCache = function() {
var current = window.location.href;
if (current.indexOf('requestTime') == -1) {
var timestamp = +new Date();
window.location.href = current + '?requestTime=' + timestamp;
}
}
window.addEventListener('load', disableCache);
</script>
</body>
</html>
//servlet
package upload;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.RequestContext;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
import utility.FileProperties;
/**
* Servlet implementation class BlobUpload
*/
public class BlobUpload extends HttpServlet {
private static final long serialVersionUID = 1L;
int count = 0;
int current = 0;
int offset = 0;
int size = 0;
HttpSession session;
long timestamp = 0;
String regularName = "";
int total = 0;
FileProperties fileProperties;
/**
* #see HttpServlet#HttpServlet()
*/
public BlobUpload() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String temp = this.getServletContext().getRealPath("/temp/");
String path = this.getServletContext().getRealPath("/attachment/");
String parts = this.getServletContext().getRealPath("/cache/");
File tempDir = new File(temp);
if(!tempDir.exists()) {
tempDir.mkdir();
}
File partsDir = new File(parts);
if(!partsDir.exists()) {
partsDir.mkdir();
}
DiskFileItemFactory dfifBlob = new DiskFileItemFactory();
dfifBlob.setRepository(tempDir);
dfifBlob.setSizeThreshold(1024 * 1024);
RequestContext rcBlob = new ServletRequestContext(request);
ServletFileUpload sfuBlob = new ServletFileUpload(dfifBlob);
sfuBlob.setFileSizeMax(1073741824);
sfuBlob.setSizeMax(1073741824);
List<FileItem> blobPart = sfuBlob.parseRequest(rcBlob);
session = request.getSession(true);
if(session.getAttribute("newFile") == null || ((boolean)session.getAttribute("newFile")) == false) {
session.setAttribute("newFile", true);
timestamp = System.currentTimeMillis();
for(FileItem currentBlob : blobPart) {
if(currentBlob.isFormField()) {
String fieldName = currentBlob.getFieldName();
if(fieldName.equals("total")) {
total = Integer.parseInt(currentBlob.getString("UTF-8"));
}else if(fieldName.equals("current")) {
current = Integer.parseInt(currentBlob.getString("UTF-8"));
}else if(fieldName.equals("offset")) {
offset = Integer.parseInt(currentBlob.getString("UTF-8"));
}else if(fieldName.equals("size")) {
size = Integer.parseInt(currentBlob.getString("UTF-8"));
}else if(fieldName.equals("regularName")) {
regularName = currentBlob.getString("UTF-8");
}
}else {
String cacheDir = parts + timestamp + "/";
File temporary = new File(cacheDir);
if(!temporary.exists()) {
temporary.mkdir();
}
File cache = new File(cacheDir + timestamp + "-" +count + ".bin");
cache.createNewFile();
if(currentBlob.getName() != null && !currentBlob.equals("")) {
InputStream input = currentBlob.getInputStream();
FileOutputStream output = new FileOutputStream(cache);
byte[] buffer = new byte[1024];
int len = 0;
while((len = input.read(buffer)) > 0) {
output.write(buffer, 0, len);
}
output.close();
input.close();
}
}
}
fileProperties = new FileProperties(timestamp, size, regularName, total);
session.setAttribute("properties", fileProperties);
session.setAttribute("fileOffset", offset);
count++;
session.setAttribute("count", count);
if(count == total) {
fileProperties.setClear(true);
fileProperties.setFinish(true);
session.removeAttribute("properties");
session.setAttribute("properties", fileProperties);
}
}else {
fileProperties = (FileProperties)session.getAttribute("filePropertie");
timestamp = fileProperties.getTimestamp();
count = (int)session.getAttribute("count");
for(FileItem currentBlob : blobPart) {
if(currentBlob.isFormField()) {
String fieldName = currentBlob.getFieldName();
if(fieldName.equals("total")) {
total = Integer.parseInt(currentBlob.getString("UTF-8"));
}else if(fieldName.equals("current")) {
current = Integer.parseInt(currentBlob.getString("UTF-8"));
}else if(fieldName.equals("offset")) {
offset = Integer.parseInt(currentBlob.getString("UTF-8"));
}else if(fieldName.equals("size")) {
size = Integer.parseInt(currentBlob.getString("UTF-8"));
}else if(fieldName.equals("regularName")) {
regularName = currentBlob.getString("UTF-8");
}
}else {
String cacheDir = parts + timestamp + "/";
File cache = new File(cacheDir + timestamp + "-" +count + ".bin");
cache.createNewFile();
if(currentBlob.getName() != null && !currentBlob.equals("")) {
InputStream input = currentBlob.getInputStream();
FileOutputStream output = new FileOutputStream(cache);
byte[] buffer = new byte[1024];
int len = 0;
while((len = input.read(buffer)) > 0) {
output.write(buffer, 0, len);
}
output.close();
input.close();
}
}
}
session.setAttribute("fileOffset", offset);
count++;
session.setAttribute("count", count);
if(count == total) {
fileProperties.setClear(true);
fileProperties.setFinish(true);
session.removeAttribute("properties");
session.setAttribute("properties", fileProperties);
}
}
fileProperties = (FileProperties)session.getAttribute("properties");
if(fileProperties.isFinish()) {
File preCombine = new File(parts + fileProperties.getTimestamp() + "/");
File[] combining = preCombine.listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
// TODO Auto-generated method stub
return pathname.getName().endsWith(".bin");
}});
String export = path + fileProperties.getRegularName();
File combined = new File(export);
if(!combined.exists()) {
combined.createNewFile();
}
for(File processing : combining) {
FileInputStream processingInput = new FileInputStream(processing);
FileOutputStream processingOutput = new FileOutputStream(combined,true);
byte[] processingBuffer = new byte[1024];
int len = 0;
while((len = processingInput.read(processingBuffer)) > 0) {
processingOutput.write(processingBuffer, 0, len);
}
processingOutput.close();
processingInput.close();
}
File[] del = preCombine.listFiles();
int j = 0;
for(int i = 0; i < del.length; i++) {
if(del[i].exists()) {
del[i].delete();
}
}
preCombine.delete();
session.removeAttribute("newFile");
session.removeAttribute("count");
session.removeAttribute("properties");
}
}
}
Why the browser prompt the error.File is a blob.
enter image description here
The FileReader interface is part of the W3C File API that is still just a working draft so you can expect it to be inconsistenly implemented across browsers.
ECMA-262 specifies slice as String.prototype.slice(start, end) where start and end reference characters in a string. I expect that if start == end then nothing will be sliced.
The W3C File API working draft specifies File.slice(start, length[, contentType]) where start and length are byte offsets. The optional contentType parameter may allow setting the content to ASCII text or similar.
So it appears that Chrome's File.slice may well be implemented per the ECMA-262 String method rather than the W3C File API method.
Related
In ASP.NET MVC Core(.NET6) I must Encrypt data in client side with publickey that I call from server with Ajax and send this encrypted data to the server side to decrypt with privatekey.
Javascript code is as following:
(() => {
const getPublicKeyButton = document.querySelector(".aes-cbc .publicKey");
getPublicKeyButton.addEventListener("click", () => {
getPublicKey();
});
function getPublicKey() {
$.ajax({
type: "GET",
traditional: true,
async: false,
cache: false,
url: 'https://localhost:7203/Home/RSA',
success: function (result) {
encrypt(result.returnValue)
},
error: function (xhr) {
console.log(xhr.responseText);
alert("Error has occurred..");
}
});
}
function getSpkiDer(spkiPem) {
const pemHeader = "<RSAKeyValue><Modulus>";
const pemFooter = "</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
var pemContents = spkiPem.substring(
pemHeader.length,
spkiPem.length - pemFooter.length
);
var binaryDerString = window.atob(pemContents);
return str2ab(binaryDerString);
}
async function importPublicKey(spkiPem) {
return await window.crypto.subtle.importKey(
"spki",
getSpkiDer(spkiPem),
{
name: "RSA-OAEP",
hash: "SHA-256",
},
true,
["encrypt"]
);
}
async function encryptRSA(key, plaintext) {
let encrypted = await window.crypto.subtle.encrypt(
{
name: "RSA-OAEP",
},
key,
plaintext
);
return encrypted;
}
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
async function encrypt(publicKey) {
const pub = await importPublicKey(publicKey);
const encrypted = await encryptRSA(
pub,
new TextEncoder().encode(document.querySelector("#firstName").value)
);
const encryptedBase64 = window.btoa(ab2str(encrypted));
var xhr = new XMLHttpRequest();
var url = `https://localhost:7203/Home/Decrypt?data=${encryptedBase64}`
xhr.open("Post", url, true);
xhr.send();
}
})();
The HTML is as following:
<div class="row" style="margin-top: 30px">
<section class="encrypt-decrypt aes-cbc">
<section class="row" dir="rtl" style="float: right">
<div class="row" style="margin-right: 40px; margin-bottom: 10px">
<input class="col-lg-7 col-md-7 col-sm-7" type="text" id="firstName" name="message">
<label class="col-lg-5 col-md-5 col-sm-5" for="firstName">FirstName:</label>
</div>
<div style="margin-right: 160px; margin-top: 30px">
<input class="publicKey" type="button" value="GetPublickey">
</div>
</section>
</section>
</div>
C# backend code is as following:
[HttpGet]
public JsonResult RSA()
{
RSACryptoServiceProvider initialProvider = new RSACryptoServiceProvider(1024);
_privateKey = ExportPrivateKey(initialProvider);
_publicKey = ExportPublicKey(initialProvider);
return Json(new { returnValue = _publicKey });
}
public static string ExportPrivateKey(RSACryptoServiceProvider csp)
{
StringWriter outputStream = new StringWriter();
if (csp.PublicOnly) throw new ArgumentException("CSP does not contain a private key", "csp");
var parameters = csp.ExportParameters(true);
using (var stream = new MemoryStream())
{
var writer = new BinaryWriter(stream);
writer.Write((byte)0x30);
using (var innerStream = new MemoryStream())
{
var innerWriter = new BinaryWriter(innerStream);
EncodeIntegerBigEndian(innerWriter, new byte[] { 0x00 });
EncodeIntegerBigEndian(innerWriter, parameters.Modulus);
EncodeIntegerBigEndian(innerWriter, parameters.Exponent);
EncodeIntegerBigEndian(innerWriter, parameters.D);
EncodeIntegerBigEndian(innerWriter, parameters.P);
EncodeIntegerBigEndian(innerWriter, parameters.Q);
EncodeIntegerBigEndian(innerWriter, parameters.DP);
EncodeIntegerBigEndian(innerWriter, parameters.DQ);
EncodeIntegerBigEndian(innerWriter, parameters.InverseQ);
var length = (int)innerStream.Length;
EncodeLength(writer, length);
writer.Write(innerStream.GetBuffer(), 0, length);
}
var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
outputStream.Write("<RSAKeyValue><Modulus>\n");
for (var i = 0; i < base64.Length; i += 64)
{
outputStream.Write(base64, i, Math.Min(64, base64.Length - i));
outputStream.Write("\n");
}
outputStream.Write("</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>");
}
return outputStream.ToString();
}
public static string ExportPublicKey(RSACryptoServiceProvider csp)
{
StringWriter outputStream = new StringWriter();
var parameters = csp.ExportParameters(false);
using (var stream = new MemoryStream())
{
var writer = new BinaryWriter(stream);
writer.Write((byte)0x30);
using (var innerStream = new MemoryStream())
{
var innerWriter = new BinaryWriter(innerStream);
innerWriter.Write((byte)0x30);
EncodeLength(innerWriter, 13);
innerWriter.Write((byte)0x06);
var rsaEncryptionOid = new byte[] { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
EncodeLength(innerWriter, rsaEncryptionOid.Length);
innerWriter.Write(rsaEncryptionOid);
innerWriter.Write((byte)0x05);
EncodeLength(innerWriter, 0);
innerWriter.Write((byte)0x03);
using (var bitStringStream = new MemoryStream())
{
var bitStringWriter = new BinaryWriter(bitStringStream);
bitStringWriter.Write((byte)0x00);
bitStringWriter.Write((byte)0x30);
using (var paramsStream = new MemoryStream())
{
var paramsWriter = new BinaryWriter(paramsStream);
EncodeIntegerBigEndian(paramsWriter, parameters.Modulus);
EncodeIntegerBigEndian(paramsWriter, parameters.Exponent);
var paramsLength = (int)paramsStream.Length;
EncodeLength(bitStringWriter, paramsLength);
bitStringWriter.Write(paramsStream.GetBuffer(), 0, paramsLength);
}
var bitStringLength = (int)bitStringStream.Length;
EncodeLength(innerWriter, bitStringLength);
innerWriter.Write(bitStringStream.GetBuffer(), 0, bitStringLength);
}
var length = (int)innerStream.Length;
EncodeLength(writer, length);
writer.Write(innerStream.GetBuffer(), 0, length);
}
var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
outputStream.Write("<RSAKeyValue><Modulus>\n");
for (var i = 0; i < base64.Length; i += 64)
{
outputStream.Write(base64, i, Math.Min(64, base64.Length - i));
outputStream.Write("\n");
}
outputStream.Write("</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>");
}
return outputStream.ToString();
}
private static void EncodeLength(BinaryWriter stream, int length)
{
if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");
if (length < 0x80)
{
stream.Write((byte)length);
}
else
{
var temp = length;
var bytesRequired = 0;
while (temp > 0)
{
temp >>= 8;
bytesRequired++;
}
stream.Write((byte)(bytesRequired | 0x80));
for (var i = bytesRequired - 1; i >= 0; i--)
{
stream.Write((byte)(length >> (8 * i) & 0xff));
}
}
}
private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true)
{
stream.Write((byte)0x02);
var prefixZeros = 0;
for (var i = 0; i < value.Length; i++)
{
if (value[i] != 0) break;
prefixZeros++;
}
if (value.Length - prefixZeros == 0)
{
EncodeLength(stream, 1);
stream.Write((byte)0);
}
else
{
if (forceUnsigned && value[prefixZeros] > 0x7f)
{
EncodeLength(stream, value.Length - prefixZeros + 1);
stream.Write((byte)0);
}
else
{
EncodeLength(stream, value.Length - prefixZeros);
}
for (var i = prefixZeros; i < value.Length; i++)
{
stream.Write(value[i]);
}
}
}
The last part in backend is as following that decrypt the encrypted data sending from javascript:
private static string _privateKey;
private static string _publicKey;
[HttpPost]
public void Decrypt(string data)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(data);
var asdsw = System.Convert.ToBase64String(plainTextBytes);
var encrypted = Convert.FromBase64String(asdsw);
using var privateKey = new RSACryptoServiceProvider();
privateKey.FromXmlString(_privateKey);
var decryptedBytes = privateKey.Decrypt(encrypted, false);
var dectryptedText = Encoding.UTF8.GetString(decryptedBytes);
}
when the Decrypt method is called then the error 'The length of the data to decrypt is not valid for the size of this key.'
will be raised in the following code:
var decryptedBytes = privateKey.Decrypt(encrypted, false);
How can I solve this problem? Any help will be appriciated.
I am trying to create a PDF from a server-side controller (report) (ireport) with ajax (and so on), and try to return the data to pdfwriter, servletoutputstream, and httpservletresponse. (I do not know exactly what I'm doing, but I'm doing it this way).
The original purpose was to send a server-side pdf file to the client, find the printer and print without a preview window.
Among them, I wrote 'application / pdf' on the server side and 'datetype: text' on the client side ajax (there is an error if I do not use ajax datatype: text)
If you print the results to the console, they will only be listed as unknown code.
Currently I am trying to put it into an iframe frame.
Question!
1. What should I do to use the text string sent to server -> client as pdf or script code?
(I have already asked you two weeks ago)
2. How do I send a pdf to server -> client? I would like to apply it to the screen by expressing it directly in code instead of downloading it. To print out.
ENG)>
// I used ajax only, because I dont know any other way
$.ajax({
url : "url",
data : JSON.stringify(data),
dataType : "text",
type: "POST",
contentType: 'application/json; charset=utf-8',
async : false,
success: function(result){
// I want to view PDF contents and directly print to PDF.
}
})
public Params createIbExItemLabelReport(HttpServletRequest resq, HttpSession session, Params inParams, HttpServletResponse resp) throws Exception{
Params outParams = ParamsFactory.createParams(inParams);
resp.setHeader("Cache-Control", "no-cache");
resp.setHeader("Pragma", "no-cache");
resp.setHeader("Expires", "0");
List<DataRow> list = new ArrayList<DataRow>();
String reportCd = "15";
String fileName = "ibExItemLabel"+reportCd+"Report";
String nullJpgFile = "";
int flag = 0;
int nullCheck = 0;
for(DataRow dr : inParams.getDataTable("dt_data")){
String imgName = "c:\\WMS\\LABEL\\FIAC021_" +reportCd + ".jpg";
File f = new File(imgName);
if (!f.isFile()) {
flag = 1;
if(nullCheck != 0){
nullJpgFile += ", ";
}
nullJpgFile += "FIAC021";
nullCheck++;
continue;
}
String bacodeCd = "FIAC02120180416001";
dr.setParam("imgName", imgName);
dr.setParam("bacodeCd", bacodeCd);
list.add(dr);
}
if(flag == 1){
outParams.setParam("ERROR_FILE", "제품코드 ["+nullJpgFile+"]의 라벨 사이즈" + reportCd + "인 파일이 존재하지않습니다.");
return outParams;
}
String appPath = session.getServletContext().getRealPath("/");
String pdfPath = null;
List<DataRow> list2 = new ArrayList<DataRow>();
for(int i = 0; i < list.size(); i++){
for(int j = 0; j < list.get(i).getInt("printQty"); j++){
list2.add(list.get(i));
}
}
Report report = new Report();
pdfPath = report.reportToPdf(session, list2, fileName);
outParams.setParam("fileName", pdfPath);
System.out.println("Found! FileName is ' : "+ pdfPath);
pdfPath = appPath + pdfPath;
pdfPath = pdfPath.replace("//", "/");
ServletOutputStream servletOutput = resp.getOutputStream();
PdfWriter pdfWriter = null;
StringBuffer pdfJs = null;
ByteArrayOutputStream pdfOutput = null;
InputStream pdfInput = null;
PdfReader pdfReader = null;
PdfStamper pdfStamper = null;
pdfOutput = convertPDFToByteArrayOutputStream(pdfPath);
int printCopy = 1;
if (printCopy == 0) {
printCopy = 1;
}
if (printCopy > 1) {
PdfCopyFields pdfPrintCopy = new PdfCopyFields(pdfOutput);
for (int i = 0; i < printCopy; i++) {
pdfPrintCopy.addDocument(new PdfReader(outputToInputStream(pdfOutput)));
}
pdfPrintCopy.close();
}
pdfInput = outputToInputStream(pdfOutput);
pdfReader = new PdfReader(pdfInput);
pdfStamper = new PdfStamper(pdfReader, servletOutput);
pdfWriter = pdfStamper.getWriter();
String printerNm = "SINDOH D410 Series PCL";
pdfWriter.setViewerPreferences(PdfWriter.HideMenubar | PdfWriter.HideToolbar | PdfWriter.HideWindowUI);
pdfJs = new StringBuffer();
pdfJs.append("var param=this.getPrintParams();\r");
pdfJs.append("param.printerName=\"").append(printerNm).append("\";\r");
pdfJs.append("param.interactive=param.constants.interactionLevel.silent;\r");
pdfJs.append("param.pageHandling=param.constants.handling.shrink;\r");
pdfJs.append("this.print(param);\r");
pdfJs.append("this.closeDoc();");
pdfWriter.addJavaScript(pdfJs.toString(), false);
servletOutput.flush();
Log.debug("servletOutput " );
if (pdfInput != null) {
try {
pdfInput.close();
} catch (Exception e) {
}
pdfInput = null;
}
if (pdfOutput != null) {
try {
pdfOutput.close();
} catch (Exception e) {
}
pdfOutput = null;
}
if (pdfReader != null) {
pdfReader.close();
pdfReader = null;
}
pdfWriter = null;
try {
if (pdfStamper != null) {
pdfStamper.close();
pdfStamper = null;
}
} catch (Exception e) {
}
resp.setHeader("Content-Disposition", "inline; filename="+pdfPath);
resp.setHeader("Content-Type", "application/pdf; charset=UTF-8");
resp.setCharacterEncoding("UTF-8");
Log.debug("before outParams " );
return outParams;
}
private InputStream outputToInputStream(ByteArrayOutputStream source) {
return new ByteArrayInputStream(source.toByteArray());
}
private static ByteArrayOutputStream convertPDFToByteArrayOutputStream(String FilePath) {
InputStream inputStream = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
inputStream = new FileInputStream(new File(FilePath));
byte[] buffer = new byte[1024];
baos = new ByteArrayOutputStream();
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return baos;
}
please answer my question
I want to export a csv file created in JS and let people download it on their phone.
This is my JS code for creating the file:
var createACSVFile = function () {
var ArrayOfDataToExport = [];
for (var k = 0; k < localStorage.length; k++) {
console.log([localStorage.key(k),JSON.parse(localStorage.getItem(localStorage.key(k)))]);
ArrayOfDataToExport.push([localStorage.key(k),JSON.parse(localStorage.getItem(localStorage.key(k)))])
}
var csvRows = [];
for(var i=0, l=ArrayOfDataToExport.length; i<l; ++i){
csvRows.push(ArrayOfDataToExport[i].join(','));
}
var csvString = csvRows.join("%0A");
var a = document.createElement('a');
a.href = 'data:attachment/csv,' + csvString;
a.target = '_blank';
a.download = 'exportFile.csv';
document.body.appendChild(a);
a.click();
};
createACSVFile();
This is my android code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = (WebView) this.findViewById(R.id.webView);
view.getSettings().setJavaScriptEnabled(true);
view.getSettings().setAllowFileAccess(true);
view.getSettings().setDomStorageEnabled(true);
view.getSettings().setUseWideViewPort(true);
view.getSettings().setLoadWithOverviewMode(true);
view.setInitialScale(1);
view.getSettings().setJavaScriptEnabled(true);
view.getSettings().setSupportZoom(false);
view.setWebViewClient(new MyBrowser(){
#Override
public void onPageFinished(WebView view, String url) {
//hide loading image
findViewById(R.id.imageLoading1).setVisibility(View.GONE);
//show webview
findViewById(R.id.webView).setVisibility(View.VISIBLE);
}
});
view.loadUrl("file:///android_asset/www/index.html");
view.setWebChromeClient(new WebChromeClient(){
});
view.setDownloadListener(new DownloadListener() {
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
});
}
I get this error:
08-20 11:12:36.508
17111-17111/checker.coin.crypto.wingcrony.by.cryptocoinchecker
E/AndroidRuntime: FATAL EXCEPTION: main
Process: checker.coin.crypto.wingcrony.by.cryptocoinchecker, PID:
17111
android.content.ActivityNotFoundException: No Activity found to handle
Intent { act=android.intent.action.VIEW
dat=data:attachment/csv,Poloniex,
currencyForToShow,usd
howToOrder,Shortname
passS,false
whichExchangeYouUse,Bitfinex }
at
android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1809)
at
android.app.Instrumentation.execStartActivity(Instrumentation.java:1523)
at android.app.Activity.startActivityForResult(Activity.java:3981)
at android.app.Activity.startActivityForResult(Activity.java:3933)
at android.app.Activity.startActivity(Activity.java:4272)
at android.app.Activity.startActivity(Activity.java:4240)
at
checker.coin.crypto.wingcrony.by.cryptocoinchecker.MainActivity$3.onDownloadStart(MainActivity.java:153)
at
com.android.webview.chromium.WebViewContentsClientAdapter.onDownloadStart(WebViewContentsClientAdapter.java:1195)
at
org.chromium.android_webview.AwContentsClientCallbackHelper$MyHandler.handleMessage(AwContentsClientCallbackHelper.java:126)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5728)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
Update
If add this to my androidManifest.xml I get the same error:
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
What I did was I generate the data I need to export to csv in the JS like this:
var generateTheDataToExportToArrayString = function () {
var ArrayOfDataToExport = [];
for (var k = 0; k < localStorage.length; k++) {
var keyName = (localStorage.key(k));
var data = JSON.parse(localStorage.getItem(localStorage.key(k)));
}
var String = '[';
for (var i = 0; i < ArrayOfDataToExport.length; i++){
if (typeof ArrayOfDataToExport[i][1] === "object"){
String += "[" + ArrayOfDataToExport[i][0] + ",";
if (ArrayOfDataToExport[i][1].length > 1 || ArrayOfDataToExport[i][1].length === 0){
if (ArrayOfDataToExport[i][1].length === 0){
String += '[' + '' + ']]';
}
else {
for (var k = 0; k < ArrayOfDataToExport[i][1].length; k++){
String += '[';
for (var l = 0; l < ArrayOfDataToExport[i][1][k].length - 1; l++){
String += ArrayOfDataToExport[i][1][k][l]+ ",";
}
String += ArrayOfDataToExport[i][1][k][ArrayOfDataToExport[i][1][k].length - 1] + "],";
}
String = String.slice(0, -1);
String += "],";
}
}
else {
String += "[";
for (var j = 0; j < ArrayOfDataToExport[i][1].length - 2; j++){
String += ArrayOfDataToExport[i][1][j] + ",";
}
String += ArrayOfDataToExport[i][1][ArrayOfDataToExport[i][1].length - 1] + "]],";
}
}
else {
String += "[" + ArrayOfDataToExport[i][0] + ",";
String += ArrayOfDataToExport[i][1] + "],";
}
}
String = String.slice(0, -1);
String += "]";
console.log(String);
};
You say the last thing I do is log that string. Well that I will capture in the Java code like this:
public void onConsoleMessage(String message, int lineNumber, String sourceID) {
if (sourceID.equals("file:///android_asset/www/assets/js/parseTest.js") && lineNumber == 184 ){
generateNoteOnSD(getBaseContext(),"export.csv", message);
}
}
This is the function generateNoteOnSD:
public void generateNoteOnSD(Context context, String sFileName, String sBody) {
try {
File root = new File(Environment.getExternalStorageDirectory(), "Backup_Data_For_AltFolio");
if (!root.exists()) {
root.mkdirs();
}
File gpxfile = new File(root, sFileName);
FileWriter writer = new FileWriter(gpxfile);
writer.append(sBody);
writer.flush();
writer.close();
Toast.makeText(context, "Saved", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
I am returning a list from my Controller as list to view and I am passing this list object to my javascript function like this
window.onload = function() {
showDirectory("$(S3DirectoryList)");
};
S3DirectoryList is the object that is returned from controller.
This is my model class
class Directory {
String folderName;
HashMap< String, String> objects;
List<Directory> dChild;
}
I want to use the folderName property of Directory in function.
Currently my javascript function is defined like this
function showDirectory( dirList) {
var markup="";
<c:forEach var="dir" items="dirList">
markup += ${dir.folderName} + "<br>";
</c:forEach>
document.getElementById("dispdir").innerHTML = markup;
}
I added some code to your Directory class. If you run it(I also added a Main method for testing purposes), you see it creates a list of directories and serializes this list as JSON. I added a constructor to make it easy to create some directories. I also added a getJSON method that serializes a directory. I added a getJSON(List directories) method to serialize a list of directories.
If you see to it this serialized list gets into your variable S3DirectoryList you can pass it to your javascript function as follows:
function showDirectory(dirList) {
var markup = "";
for(var i = 0; i < dirList.length; i++) {
markup += dirList[i].folderName + "<br />";
}
document.getElementById("dispdir").innerHTML = markup;
}
window.onload = function() {
showDirectory($(S3DirectoryList));
};
the Directory class:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class Directory{
String folderName;
HashMap<String, String> objects;
List<Directory> dChild;
public Directory(String folderName, String[] objects) {
this.folderName = folderName;
this.objects = new HashMap<String, String>();
for(int i = 0; i < objects.length; i = i + 2) {
this.objects.put(objects[i], objects[i + 1]);
}
this.dChild = new ArrayList<Directory>();
}
public void addChildDirectory(Directory childDirectory) {
if(this.dChild == null)
this.dChild = new ArrayList<Directory>();
this.dChild.add(childDirectory);
}
public String toJSON() {
StringBuilder b = new StringBuilder();
b.append("{");
b.append("'folderName': '").append(folderName == null ? "" : folderName).append("'");
b.append(",objects: {");
if(objects != null) {
Iterator<Map.Entry<String, String>> objectsIterator = objects.entrySet().iterator();
if(objectsIterator.hasNext()) {
Map.Entry<String, String> object = objectsIterator.next();
b.append("'").append(object.getKey()).append("': '").append(object.getValue()).append("'");
}
while (objectsIterator.hasNext()) {
Map.Entry<String, String> object = objectsIterator.next();
b.append(",'").append(object.getKey()).append("': '").append(object.getValue()).append("'");
}
}
b.append("}");
b.append(",'dChild': ");
b.append("[");
if(dChild != null) {
if(dChild.size() > 0)
b.append(dChild.get(0).toJSON());
for(int i = 1; i < dChild.size(); i++) {
b.append(",").append(dChild.get(i).toJSON());
}
}
b.append("]");
b.append("}");
return b.toString();
}
public static String getJSON(List<Directory> directories) {
StringBuilder b = new StringBuilder();
b.append("[");
if(directories.size() > 0)
b.append(directories.get(0).toJSON());
for(int i = 1; i < directories.size(); i++) {
b.append(",").append(directories.get(i).toJSON());
}
b.append("]");
return b.toString();
}
private static Directory generateDirectory(int seed) {
List<Directory> directories = new ArrayList<Directory>();
for(int i = 0; i < 5; i++) {
directories.add(
new Directory(
"folderName_" + seed + "_" + i,
new String[]{"k_" + seed + "_" + i + "_1", "v_" + seed + "_" + i + "_1", "k_" + seed + "_" + i + "_2", "k_" + seed + "_" + i + "_2"}));
}
Directory directory_root = directories.get(0);
Directory directory_1_0 = directories.get(1);
Directory directory_1_1 = directories.get(2);
Directory directory_1_0_0 = directories.get(3);
Directory directory_1_0_1 = directories.get(4);
directory_root.addChildDirectory(directory_1_0);
directory_root.addChildDirectory(directory_1_1);
directory_1_0.addChildDirectory(directory_1_0_0);
directory_1_0.addChildDirectory(directory_1_0_1);
return directory_root;
}
public static void main(String[] args) {
List<Directory> directories = new ArrayList<Directory>();
for(int i = 0; i < 2; i++) {
directories.add(generateDirectory(i));
}
System.out.println(toJSON(directories));
}
}
I have public key in XML that created in C#
the format is:
<Modulus>rYDd94biRAJ1P6j68xjARl......and so on</Modulus>
<Exponent>A**B</Exponent>
I want to create this key in Javascript, and encrypt string with it,
how can I do it?
Thanks,
After so many hours researching, testing, giving up, researching again, etc., for a solution on RSA interoperability for .NET and Javascript, I have found this library:
http://www.jocys.com/Common/JsClasses/Documents/
Their classes have the same working code as the RSACryptoServiceProvider on the server.
What you have to do:
Download the source code from their Github :
https://github.com/JocysCom/JsClasses/archive/master.zip
Rename the files from *.debug.js to *.js. See the list of files below, on (3).
Add the required files to your html page
<script type="text/javascript" src="js/System.js"></script>
<script type="text/javascript" src="js/System.IO.js"></script>
<script type="text/javascript" src="js/System.Text.js"></script>
<script type="text/javascript" src="js/System.Convert.js"></script>
<script type="text/javascript" src="js/System.BigInt.js"></script>
<script type="text/javascript" src="js/System.BitConverter.js"></script>
<script type="text/javascript" src="js/System.Security.Cryptography.js"></script>
<script type="text/javascript" src="js/System.Security.Cryptography.SHA1.js"></script>
<script type="text/javascript" src="js/System.Security.Cryptography.HMACSHA1.js"></script>
<script type="text/javascript" src="js/System.Security.Cryptography.RSA.js"></script>
Add this javascript code to encrypt your text:
function RsaEncrypt()
{
//a public key generated from their sample.
//your should generate yours and stamp it here.
var xmlParams =
"<RSAKeyValue>" +
"<Modulus>pxtmFnrGI6Sb8ziyY+NRUDuQ4b/ETw5WabQ4daFQqzsCEr/6J/LLBU/2D5mO5/Wu5U/Rya1E55aYFZeaZMNqAw==</Modulus>" +
"<Exponent>AQAB</Exponent>" +
"<P>2TsVXWPEvDIJv/gd2rX9k0UOyXuaYgoAchIH6vUicis=</P>" +
"<Q>xO4+OYREQfqYRQK7y73+RaUG0IxobT0OQ0c+Ok2hc4k=</Q>" +
"<DP>K7/xgpiIU9rECeyfnp/OjS14V+3T3vDivBaTj6eFI3c=</DP>" +
"<DQ>K4N9ClZ4gp+tn6oP9t//XEIvtEsiE+kmyqTmUhmvMAk=</DQ>" +
"<InverseQ>p7o4BOlKZQZ693R1ViZ66y5gTjUkNNTd2za7/1YGBCs=</InverseQ>" +
"<D>XZqFVrYy4qhECruJgVZFp/GVuD5Y0gev88nVjl5r911QT+I8vgJSklTso7jTlpMtf2oe7UZ0WRWEtgPS3tZn4Q==</D>" +
"</RSAKeyValue>";
var rsa = new System.Security.Cryptography.RSACryptoServiceProvider();
rsa.FromXmlString(xmlParams);
// Encrypt
var decryptedBytes = System.Text.Encoding.UTF8.GetBytes(text);
var doOaepPadding = true;
var encryptedBytes = rsa.Encrypt(decryptedBytes, doOaepPadding);
var encryptedString = System.Convert.ToBase64String(encryptedBytes);
return encryptedString;
}
Look for documentation (link above) on how to generate the private and public keys. The code is quite the same as you would manually write .NET on server.
You can also check their test page
Also you can save public key in PEM format in C#:
private static string ExportPublicKey(RSACryptoServiceProvider csp)
{
var parameters = csp.ExportParameters(false);
using (var stream = new MemoryStream())
{
var writer = new BinaryWriter(stream);
writer.Write((byte)0x30); // SEQUENCE
using (var innerStream = new MemoryStream())
{
var innerWriter = new BinaryWriter(innerStream);
EncodeIntegerBigEndian(innerWriter, new byte[] { 0x00 }); // Version
EncodeIntegerBigEndian(innerWriter, parameters.Modulus);
EncodeIntegerBigEndian(innerWriter, parameters.Exponent);
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.D
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.P
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.Q
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.DP
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.DQ
EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.InverseQ
var length = (int)innerStream.Length;
EncodeLength(writer, length);
writer.Write(innerStream.GetBuffer(), 0, length);
}
char[] base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
StringBuilder res = new StringBuilder();
res.AppendLine("-----BEGIN RSA PUBLIC KEY-----");
for (int i = 0; i < base64.Length; i += 64)
{
int l = Math.Min(64, base64.Length - i);
for (int j = 0; j < l; j++) res.Append(base64[i + j]);
res.AppendLine();
}
res.AppendLine("-----END RSA PUBLIC KEY-----");
return res.ToString();
}
}
private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true)
{
stream.Write((byte)0x02); // INTEGER
var prefixZeros = 0;
for (var i = 0; i < value.Length; i++)
{
if (value[i] != 0) break;
prefixZeros++;
}
if (value.Length - prefixZeros == 0)
{
EncodeLength(stream, 1);
stream.Write((byte)0);
}
else
{
if (forceUnsigned && value[prefixZeros] > 0x7f)
{
// Add a prefix zero to force unsigned if the MSB is 1
EncodeLength(stream, value.Length - prefixZeros + 1);
stream.Write((byte)0);
}
else
{
EncodeLength(stream, value.Length - prefixZeros);
}
for (var i = prefixZeros; i < value.Length; i++)
{
stream.Write(value[i]);
}
}
}
private static void EncodeLength(BinaryWriter stream, int length)
{
if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");
if (length < 0x80)
{
// Short form
stream.Write((byte)length);
}
else
{
// Long form
var temp = length;
var bytesRequired = 0;
while (temp > 0)
{
temp >>= 8;
bytesRequired++;
}
stream.Write((byte)(bytesRequired | 0x80));
for (var i = bytesRequired - 1; i >= 0; i--)
{
stream.Write((byte)(length >> (8 * i) & 0xff));
}
}
}