I have a Java web app that serves a file:
#RequestMapping(value = "/pdf/download", method = RequestMethod.GET)
public void download(
HttpServletRequest request,
HttpServletResponse response,
#RequestParam(value = "id", required = true) Long id) throws IOException {
File pdfFile = pdfFileManager.getFromId(id);
response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "attachment; filename=download");
response.setContentLength((int) pdfFile.length());
FileInputStream fileInputStream = null;
OutputStream responseOutputStream = null;
try {
fileInputStream = new FileInputStream(pdfFile);
responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
responseOutputStream.flush();
} finally {
fileInputStream.close();
responseOutputStream.close();
}
}
I retrieve the file in the client and base64 encode it using FileReader:
$.ajax({
url: "/pdf/download?id=" + id,
dataType: "application/pdf",
processData: false
}).always(function(response) {
if(response.status && response.status === 200) {
savePdf(response.responseText, "download_" + id);
}
});
function savePdf(pdf, key) {
var blob = new Blob([pdf], {type: "application/pdf"});
var fileReader = new FileReader();
fileReader.onload = function (evt) {
var result = evt.target.result;
try {
localStorage.setItem(key, result);
} catch (e) {
console.log("Storage failed: " + e);
}
};
fileReader.readAsDataURL(blob);
}
The problem is that the value saved in the local storage is not correct. The encoded data differs from the one i get when i upload the PDF using this snip. I don't know if the problem is how i serve the file or the encoding process in the client.
The value stored is something like this
data:application/pdf;base64,JVBERi0xLjQKJe+/ve+/ve+/ve+/vQoxIDAgb...
instead of
data:application/pdf;base64,JVBERi0xLjQKJeHp69MKMSAwIG9iago8PC9Ue...
Solved the problem setting the request's response type to blob:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/pdf/download?id=" + id);
xhr.responseType = "blob";
xhr.onload = function() {
if(xhr.status && xhr.status === 200) {
savePdf(xhr.response, "download_" + id);
}
}
xhr.send();
function savePdf(pdf, key) {
var fileReader = new FileReader();
fileReader.onload = function (evt) {
var result = evt.target.result;
try {
localStorage.setItem(key, result);
} catch (e) {
console.log("Storage failed: " + e);
}
};
fileReader.readAsDataURL(pdf);
}
Related
Hello Developers,
I'm trying to download the list of files getting form XMLHttpRequest() request method and store it in the array of files. I wanted to zip all the files in an array using javascript without using any 3rd party library.
I have tried to achieve this by URL.createObjectURL(url) and URL.revokeObjectURL(url) method but the file I'm getting is corrupted.
I'm Sharing my code snippet please help me out
const URLS = [
'https://vr.josh.earth/assets/2dimages/saturnv.jpg',
'https://vr.josh.earth/assets/360images/hotel_small.jpg',
'https://vr.josh.earth/assets/360images/redwoods.jpg'
];
$(document).ready(function () {
debugger
$("#downloadAll").click(function () {
var blob = new Array();
var files = new Array();
URLS.forEach(function (url, i) {
getRawData(url, function (err, data) {
debugger
var mydata = data;
// mydata = btoa(encodeURIComponent(data));
// var blobData = b64toBlob(mydata , 'image/jpg');
var blobData = new Blob([mydata], { type: 'image/jpg' });
blob.push(blobData);
var filename = "testFiles" + i + ".jpg";
var file = blobToFile(blobData, filename);
files.push(file);
debugger
if (files.length == URLS.length) {
// saveData(blob, "fileName.zip");
var AllBlobData = new Blob([blob], { type: 'application/zip' });
saveData(AllBlobData, "Test.zip");
// saveFile("DownloadFiles.zip", "application/zip", files)
}
});
});
});
});
//Retriving record using XMLHttpRequest() method.
function getRawData(urlPath, callback, progress) {
var request = new XMLHttpRequest();
request.open("GET", urlPath, true);
request.setRequestHeader('Accept', '');
if ('responseType' in request)
request.responseType = "arraybuffer"
if (request.overrideMimeType)
request.overrideMimeType('text/plain; charset=x-user-defined');
request.send();
var file, err;
request.onreadystatechange = function () {
if (this.readyState === 4) {
request.onreadystatechange = null;
if (this.status === 200) {
try {
debugger
var file = request.response || request.responseText;
} catch (error) {
throw error;
}
callback(err, file);
} else {
debugger
callback(new Error("Ajax Error!!"))
}
} else {
debugger
}
}
}
//For Saving the file into zip
var saveData = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (data, fileName) {
// var AllBlobs = new Blob([data], { type: "" });//application/zip //octet/stream
// var url = window.URL.createObjectURL(AllBlobs);
var url = window.URL.createObjectURL(data);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
}());
//Downloaded Zip File
enter image description here
I am a beginner in socket.io. I have been used a library
https://www.npmjs.com/package/socket.io-stream
We were successfully uploaded images using the browser. But now, I want to upload images from android application. If anyone have android code please give me ..
https://github.com/socketio/socket.io-client-java/issues/29
I have been searching on google, but not found any proper solution.
var imageBuffer = customJs.decodeBase64Image(base64Data);
var imageTypeDetected = imageBuffer.type.match(/\/(.*?)$/);
var filename = 'profile-' + Date.now() + '.' + imageTypeDetected[1];
// config.uploadImage --- Folder path where you want to save.
var uploadedImagePath = config.uploadImage + filename;
try {
fs.writeFile(uploadedImagePath, imageBuffer.data, function () {
dbMongo.updateImage({email: decoded.email, user_id: decoded.userId, 'profile_picture': config.showImagePath + filename}, function (res) {
if (res.error) {
socket.emit('set_update_image', {'error': 1, 'message': 'Error!' + res.message, 'data': null, 'status': 400});
} else {
console.log(res);
socket.emit('set_update_image', res);
}
});
});
} catch (e) {
socket.emit('set_update_image', {'error': 1, 'message': 'Internal server error ' + e, 'data': null, 'status': 400});
}
From other file call a function
exports.decodeBase64Image = function decodeBase64Image(dataString) {
var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
var response = {};
if (matches.length !== 3)
{
return new Error('Invalid input string');
}
response.type = matches[1];
response.data = new Buffer(matches[2], 'base64');
return response;
}
For the upload image from android using socket you need to send image as base64 string,
Following is the example for convert Image into base64 then you send data same as another paramaters.
String base64Image = getBase64Data(dirPath + "/" + fileName);
public String getBase64Data(String filePath) {
try {
InputStream inputStream = new FileInputStream(filePath);//You can get an inputStream using any IO API
byte[] bytes;
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
}
bytes = output.toByteArray();
return "data:image/jpeg;base64," + Base64.encodeToString(bytes, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
In android, you need to encode the image by using Base64
public void sendImage(String path)
{
JSONObject sendData = new JSONObject();
try{
sendData.put("imageData", encodeImage(path));
socket.emit("image",sendData);
}catch(JSONException e){
}
}
private String encodeImage(String path)
{
File imagefile = new File(path);
FileInputStream fis = null;
try{
fis = new FileInputStream(imagefile);
}catch(FileNotFoundException e){
e.printStackTrace();
}
Bitmap bm = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG,100,baos);
byte[] b = baos.toByteArray();
String encImage = Base64.encodeToString(b, Base64.DEFAULT);
//Base64.de
return encImage;
}
In server side, receive image and decode it
socket.on("image", function(info) {
var img = new Image();
img.src = 'data:image/jpeg;base64,' + info.imageData;
});
I have some problems to handle an excel file download with Ajax. I Have found this source code on an another webpage I copied that in my webproject:
$.ajax({
type: "POST",
url: "myStrutsAction.action",
data: {p1:p1, p2:p2},
success: function(response, status, xhr){
disableMyLoadingUserPopupScreen();
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
disposition);
}
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([response], { type: type });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
var a = document.createElement("a");
if (typeof a.download === 'undefined') {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100);
}
}
});
This kind of code shows the user dialog for saving or opening the specific excelfile. But if I have tried to open the Excelfile, the File are damaged and couldn´t be opened (I have viewed in Notepad++ editor, but here I see some cryptical characters):
Here is my Struts2 execute method on the server:
public String execute(){
// Create Excel File
returnFileAsStream("myExcelfile");
return null;
}
In this method I have written the HTTP Response Header:
private void returnFileAsStream(final String filename) throws IOException {
final InputStream is = new FileInputStream(filename);
OutputStream os = null;
try {
response.setContentType("application/octet-stream");
response.setHeader("Cache-Control", "maxage=3600");
response.setHeader("Pragma", "public");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
os = response.getOutputStream();
int length;
byte buf[] = new byte[1024];
while ((length = is.read(buf)) > 0) {
os.write(buf, 0, length);
}
is.close();
os.close();
} finally {
// other code, not important
}
}
It is correct, that it is not possible to handle a file download with Ajax? I´m of the opinion, that it is the problem, that I want to handle some steps with binary data instead of text data and Ajax couldn´t be handle some steps with binary code?
Set the content-type to :
For BIFF .xls files
application/vnd.ms-excel
For Excel2007 and above .xlsx files
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
I am posting the base64 clipboard image to server (node) and I am saving the base64 to disk. For some reason the image is corrupted.
Client side logic of posting:
function sendData($http, clipboardImage) {
// $http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
// var imgData = JSON.stringify(clipboardImage);
//var data = {"imgdata" : clipboardImage};
var url = "http://localhost:3000/pad/img/";
$http({
method: 'POST',
url: url,
data: "data=" + clipboardImage
});
}
$("[ng-model='html']").delegate("p", "paste", function(event) {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
console.log(JSON.stringify(items)); // will give you the mime types
// find pasted image among pasted items
var blob = null;
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") === 0) {
blob = items[i].getAsFile();
}
}
// load image if there is a pasted image
if (blob !== null) {
var reader = new FileReader();
reader.onload = function(e) {
sendData($http, e.target.result);
};
reader.readAsDataURL(blob);
}
});
Server logic:
app.post("/pad/img/", function(req, res) {
var imgB64Data = req.body.data;
var decodedImg = decodeBase64Image(imgB64Data);
var imageBuffer = decodedImg.data;
var type = decodedImg.type;
var extension = mime.extension(type);
var fileName = "image." + extension;
try {
fs.writeFile(fileName, imageBuffer, function(err) {
console.log(err);
});
} catch (err) {
console.error(err);
}
});
function decodeBase64Image(dataString) {
var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/),
response = {};
if (matches.length !== 3) {
return new Error('Invalid input string');
}
response.type = matches[1];
response.data = new Buffer(matches[2], 'base64');
return response;
}
The image is being saved successfully but it seems to be corrupted. Can you please point out what may be missing?
Have you tried explicitly setting the file encoding when calling fs.writeFile?
try {
fs.writeFile(fileName, imageBuffer, {encoding:'utf8'}, function(err) {
console.log(err);
});
} catch (err) {
console.error(err);
}
NodeJS Docs: fs.writeFile(filename, data\[, options\], callback)
In my PhoneGap project, I use navigator.device.capture.captureImage(captureSuccess, captureError, {limit : 1}); to take a picture. In captureSucces function, I get de MediaFile, and I encode it to base64 with this:
var file="";
var datafile=mediaFiles[0];
var reader = new FileReader();
reader.onload = function(evt){
file=evt.target.result;
};
reader.readAsDataURL(datafile);
I send this file to a REST Web Service, where I decode the file and save in a folder:
if (files != null) {
FileOutputStream fileOutputStream = null;
try {
byte[] byteFichero = Base64.decodeBase64(files);
System.out.println("ARCHIVO " + byteFichero);
File fich = new File(pathFichero.toString());
fich.createNewFile();
fileOutputStream = new FileOutputStream(fich);
fileOutputStream.write(byteFichero);
System.out.println("Fichero almacenado ok");
} catch (Exception e) {
System.out.println("Excepcion alamacenando fichero "
+ e.getMessage() + " " + pathFichero);
return respuesta;
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException ex) {
Logger.getLogger(
GestionFicheroObjetoService.class.getName())
.log(Level.SEVERE, null, ex);
}
pathFichero.delete(0, pathFichero.length());
}
}
Unfortunately, I get an empty image(1 KB). This is because the file value is not correct, it contains:
{"name":"1385711756945.jpg",
"fullPath":"file:///storage/sdcard0/DCIM/Camera/1385711756945.jpg",
"type":"image/jpeg",
"lastModifiedDate":1385711757000,
"size":2785413,
"start":0,
"end":0}
and when I encode this, I get a little base64 code:
[B#877d81
In other examples, they always use input type file to get the file (http://thiscouldbebetter.wordpress.com/2013/07/03/converting-a-file-to-a-base64-dataurl-in-javascript/) but I have to get the file from Camera.
What is the problem? Some other solution?
Thank you very much.
i am also facing this issue. i got solution after long time search
camera success function:
function capturesuceess(mediafiles){
var uploadimageurl= mediafile
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemSuccess, rfail);
window.resolveLocalFileSystemURI(uploadimageurl, onResolveSuccess, fail);
}
function onFileSystemSuccess(fileSystem) {
console.log(fileSystem.name);
}
function bytesToSize(bytes) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes == 0) return 'n/a';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
};
function onResolveSuccess(fileEntry) {
filenameofajax=fileEntry.name;
var efail = function(evt) {
console.log("File entry error "+error.code);
};
var win=function(file) {
console.log(file);
alert(bytesToSize(file.size));
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log("read success");
console.log(evt.target.result);
var basestr=evt.target.result;
basestr= basestr.substr(basestr.indexOf("base64,")+7,basestr.length);
console.log(basestr);// this is a base64 string
};
reader.readAsDataURL(file);
};
fileEntry.file(win, efail);
}
try this working fine. and also u write efail and fail function with empty enjoy with phonegap
The best way to do this is using navigation.camera:
https://gist.github.com/pamelafox/2173589