I´m trying to download an jpg image from amazon S3 using the NodeJs SDK. I´m able to get the file object on the backend. However when I try to create a blob object and download it from angular, I cannot open the file. When I try to open it with any image editor I get an error as if the file is damaged or incorrectly formatted.
Here´s my Node JS code:
function downloadFile(file,callback) {
//Arranging file name
var fileKey = file.lifeCycle + "/" + file.id + "." + file.extension;
// download the file via aws s3 here
console.log('Trying to download file', file.id);
var AWS = require('aws-sdk');
var s3 = new AWS.S3();
var s3Params = {
Bucket: 'myBucket',
Key: fileKey
};
/*
res.attachment(fileKey);
var fileStream = s3.getObject(s3Params).createReadStream();
fileStream.pipe(res);
*/
s3.getObject(s3Params, function (err, data) {
if (err === null) {
res.send(data);
} else {
res.status(500).send(err);
}
callback(null);
});
}
});
The angular code:
vm.fileData = new ApiDownloadFile({fileId: 1});
vm.downloadFile = function(){
console.log("Downloading...");
vm.fileData.$query()
.then(function(response){
$log.log(response);
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
console.dir(response.headers);
var blob = new Blob(response.Body.data,{type:response['content-type']});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "1.jpg";
link.click();
},function(err){
$log.log(err);
});
};
I solved the problem. The issue seemed to be with the Uint8 conversion.
I added this lines and it worked fine:
.then(function(response) {
try{
$log.log(response);
var arrayBufferView = new Uint8Array(response.Body.data); // Convert the response to fix the problem of opening the file
$log.log(arrayBufferView);
var file = new Blob( [arrayBufferView], {type: response.ContentType});
Related
I'm trying to upload a base64encoded image to Cloudinary using the following code. However, this code doesn't work. Could you guys suggest to me any solution for this, please? The post request fails with a 500 error.
const uploadProductImage = asyncHandler(async (req, res) => {
let image = req.body.image;
const cloudres = await cloudinary.v2.uploader.upload(image);
console.log(cloudres);
res.status(200);
});
Not sure if this helps, but here is a working codepen uploading a base64 encoded file.
Update the cloudname and unsigned preset to your information. Refresh the codepen and it will upload into your cloud account.
https://codepen.io/tmero/pen/poeXaPY
const cloudName = 'tessamero';
const unsignedUploadPreset = 'stackoverflowtest';
// Upload base64 encoded file to Cloudinary
uploadFile('data:image/gif;base64,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')
// *********** Upload file to Cloudinary ******************** //
function uploadFile(file) {
var url = `https://api.cloudinary.com/v1_1/${cloudName}/upload`;
var xhr = new XMLHttpRequest();
var fd = new FormData();
xhr.open('POST', url, true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function(e) {
if (xhr.readyState == 4 && xhr.status == 200) {
// File uploaded successfully
var response = JSON.parse(xhr.responseText);
// https://res.cloudinary.com/cloudName/image/upload/v1483481128/public_id.jpg
var url = response.secure_url;
// Create a thumbnail of the uploaded image, with 150px width
var tokens = url.split('/');
tokens.splice(-2, 0, 'w_150,c_scale');
var img = new Image(); // HTML5 Constructor
img.src = tokens.join('/');
img.alt = response.public_id;
document.body.appendChild(img);
}
};
fd.append('upload_preset', unsignedUploadPreset);
fd.append('tags', 'browser_upload'); // Optional - add tag for image admin in Cloudinary
fd.append('file', file);
xhr.send(fd);
}
An alternative, here is a great developer post on uploading base64encoded images with nodejs using Cloudinary by James Quick: https://dev.to/jamesqquick/cloudinary-image-upload-with-nodejs-4mad
Let me know if any of this helps!
const cloudinary = require('cloudinary').v2;
const { CloudinaryStorage } = require('multer-storage-cloudinary');
const express = require('express');
const multer = require('multer');
const app = express();
const storage = new CloudinaryStorage({
cloudinary: cloudinary,
params: {
folder: 'some-folder-name',
format: async (req, file) => 'png', // supports promises as well
public_id: (req, file) => 'computed-filename-using-request',
},
});
const parser = multer({ storage: storage });
app.post('/upload', parser.single('image'), function (req, res) {
res.json(req.file);
});
I'm using the gcloud API on a Nodejs web server to upload files. I'd prefer the files not be uploaded on the client side and instead uploaded on the server. Currently, I am producing a blob on the client side, then converting it to text and passing that to the server through a POST request. All of the information gets successfully passed from the client to the server as expected. This data is also uploaded to gcloud, however, Gcloud does not recognize this as a valid file nor does my computer when I download it.
What is the best way to get the contents of the file to gcloud from the server side? I've tried using dataURIs and reading the orignal file by text and both produce similiar issues. I've also explored piping a readFileStream from the blob on the server end but blobs are not natively supported by node so I have not done so yet.
Client Side
function readSingleFile(e, func, func2){
var file = e.target.files[0];
if(!file){
return; // Add error msg_here
}
var reader = new FileReader();
reader.onload = function(e){
let contents = e.target.result;
let img = document.createElement('img')
let cvs = document.createElement('canvas');
img.onload = ()=>{
cvs.width = img.width;
cvs.height= img.height;
let ctx = cvs.getContext('2d');
ctx.drawImage(img,0,0);
cvs.toBlob((res)=>{res.text().then((text)=>{func2(text)})}, "image/jpeg", 0.92);
}
img.src=contents;
func(contents);
}
reader.readAsDataURL(file);
}
Server Side
function publishPrintjob(dataObj){
try{
var newElemKey = database.ref().child('queue').push().key; // Get random Key
// Create a new blob in the bucket and upload the file data.
const gcloudFile = storage.file('images/' + newElemKey + '.jpg');
gcloudFile.save(dataObj.sockImageFile, function(err) {
if (!err) {
Console.log("File Uploaded!")
}
});
var data = {
date: dataObj.Date,
email: dataObj.email,
design: dataObj.Design,
author: dataObj.Author,
address: dataObj.address,
imageKey: newElemKey,
}
admin.database().ref('queue/' + newElemKey).set(data);
} catch(err){
console.log(err)
}
}
Note: func simply shows the image on the client side, func2 just adds the contents to the POST object.
Uploading a file directly from the computer would be easiest using the storage.bucket(bucketName).upload() function from the cloud storage library. However, this uses location of a file locally and thus will not work unless a file is transferred to the server and saved first. This could be achieved using multi-part form data. Using multipart or uploading locally are better methods for uploading to google storage.
Instead, I solve this by first converting the image to a dataURI, sending the data URI to the server via the body of a GET request, and then converting it to a buffer with a readable stream that can be piped to google storage.
Client
let formData = getFormData('myForm');
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
}
};
xhttp.open("POST", "dashboard", true);
xhttp.setRequestHeader('Content-Type', 'application/json');
xhttp.send(JSON.stringify(formData));
xhttp.onload = ()=> {
console.log(JSON.parse(xhttp.response))
// Handle server response here
};
}
Server
// DataObject is the body of the GET request, the property imageFile is the URI from readFileAsURI
function uploadImageOnServer(dataObj){
try{
var newElemKey = database.ref().child('queue').push().key; // Get random Key to use as filename
// Create a new blob in the bucket and upload the file data.
const gcloudFile = storage.file('images/' + newElemKey + '.jpeg');
var fs = require('fs'); // Should be required at the top of the file
var string = dataObj.ImageFile;
var regex = /^data:.+\/(.+);base64,(.*)$/;
var matches = string.match(regex);
var ext = matches[1];
var data = matches[2];
var buffer = Buffer.from(data, 'base64');
// Create the readstream
const readableInstanceStream = new Readable({
read() {
this.push(buffer);
this.push(null);
}
});
readableInstanceStream.pipe(gcloudFile.createWriteStream()) // link to gcloud storage api
.on('error', function(err) {
console.log('error')
})
.on('finish', function() {
console.log('upload complete')
});
} catch(err){
console.log(err)
}
}
I have an ASP.Net Web API method which is returning a zip file, which seems happening properly, now what I want is, I want to download that zip file at the client location using React. My Api method is as follows:
[HttpPost]
public FileContentResult Post([FromForm] string communityName, [FromForm] string files)
{
var removedInvalidCharsFromFileName = removeInvalidCharsFromFileName(files);
var tFiles = removedInvalidCharsFromFileName.Split(',');
string rootPath = Configuration.GetValue<string>("ROOT_PATH");
string communityPath = rootPath + "\\" + communityName;
byte[] theZipFile = null;
using (MemoryStream zipStream = new MemoryStream())
{
using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
foreach (string attachment in tFiles)
{
var zipEntry = zip.CreateEntry(attachment);
using (FileStream fileStream = new FileStream(communityPath + "\\" + attachment, FileMode.Open))
using (Stream entryStream = zipEntry.Open())
{
fileStream.CopyTo(entryStream);
}
}
}
theZipFile = zipStream.ToArray();
}
return File(theZipFile, "application/zip", communityName + ".zip");
}
And my React/JS method is as follows:
handleDownload = (e) => {
e.preventDefault();
var formData = new FormData();
formData.append('communityname', this.state.selectedCommunity);
formData.append('files', JSON.stringify(this.state['checkedFiles']));
let env = 'filesApi.' + clientConfiguration['Environment'];
let url = clientConfiguration['filesApi.local'];
alert(url);
axios({
method: 'post',
url: url,
data: formData
})
.then(res => {
//console.log(res.data);
var binaryData = [];
binaryData.push(res.data);
const src = window.URL.createObjectURL(new Blob(binaryData, { type: "application/zip" }));
var fileName = `${this.state['selectedCommunity']}.zip`;
saveAs(src, fileName);
});
};
It is downloading the zip file, but says the following error when I try to unzip the file at the client location, what am I missing - not able to understand:
Can not open the file as zip archive, is not archiving, Warning Headers error
, any help please
Using the sapui5 uploadcollection to upload files in the frontend and then sending them through ajax with a post request...
I need to know how to convert te returned object from the uploadcollection control into a xstring, so then I can send that xstring (that contains the file content) To a sap gateway by using ajax post method.
Any idea how could I do this?
Right now I'm sending files by using the uploadcollection, once I upload an attachment, the control returns an object that represents the file content.
I'm trying to make this object a xstring by using filereader:
//obtiene archivo
var file = files[i];
//Convierte archivo en binario
var reader = new FileReader();
reader.onload = function(readerEvt) {
var binaryString = readerEvt.target.result;
var base64 = btoa(binaryString);
var base64file;
if(typeof base64file == "undefined" || typeof base64file == null){
base64file = base64;
}else{
base64file = base64file +'new'+base64;
}
};
reader.readAsBinaryString(file);
console.log(file)
But this work only with files of type image, the others like pdf, .doc etc etc give the following error when I try to send them with ajax.
"The Data Services Request could not be understood due to malformed syntax".
Any idea how can I send convert these files into a xstring data?
Take a look at this example. Hope this helps.
View
<u:FileUploader change="onChange" fileType="pdf" mimeType="pdf" buttonText="Upload" />
Controller
convertBinaryToHex: function(buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), function(x) {
return ("00" + x.toString(16)).slice(-2);
}).join("");
},
onChange: function(oEvent){
var that = this;
var reader = new FileReader();
var file = oEvent.getParameter("files")[0];
reader.onload = function(e) {
var raw = e.target.result;
var hexString = that.convertBinaryToHex(raw).toUpperCase();
// DO YOUR THING HERE
};
reader.onerror = function() {
sap.m.MessageToast.show("Error occured when uploading file");
};
reader.readAsArrayBuffer(file);
},
I figured it out by filling an array everytime that a file was uploaded through the control,
change: function(oEvent) {
//Get file content
file = oEvent.getParameter("files")[0];
//Prepare data for slug
fixname = file.name;
filename = fixname.substring(0, fixname.indexOf("."));
extension = fixname.substring(fixname.indexOf(".") + 1);
//fill array with uploaded file
var fileData = {
file: file,
filename: filename,
extension: extension
}
fileArray.push(fileData);
},
and then I did a loop over that array to post every single file I keept there by using ajax method post.
$.each(fileArray, function(j, valor) {
//get file
file = fileArray[j].file;
//get file lenght
var numfiles = fileArray.length;
//Convert file to binary
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function(evt) {
fileString = evt.target.result;
//get and make slug
filename = fileArray[j].filename;
extension = fileArray[j].extension;
slug = documento + '/' + filename + '/' + extension;
//User url service
var sUrlUpload = "sap url";
runs++;
//Post files
jQuery.ajax({});
}
});
I am trying to upload a file to amazon S3 from a phonegap app on android. I already have the code working for iOS. But I've got a trouble making it work on android. The problem is that I do not know how to create the Blob object properly. On iOS I just do this:
blob = new Blob([evt.target.result], {type: "image/png"});
It is uploaded just fine. On android one can not use the Blob constructor (see here), but I could not manage to get the file data correctly into the Blob object using WebKitBlobBuilder.
Here is how I retrieve the file data, there are two approaches and both pass without errors, but the resulting file on the S3 is empty:
window.resolveLocalFileSystemURI(url, function(e){
e.file(function(f){
var reader = new FileReader();
reader.onloadend = function(evt) {
// This way also did not work:
// var builder = new WebKitBlobBuilder();
// builder.append(evt.target.result);
// blob = builder.getBlob("image/png");
var blob = null;
var builder = new WebKitBlobBuilder();
for(var i = 0; i < evt.target.result.length; i++){
builder.append(evt.target.result[i]);
}
blob = builder.getBlob("image/png");
uploadToS3(filename, s3url, blob);
};
reader.readAsArrayBuffer(f);
});
}, function(e){
console.log("error getting file");
error();
});
also, here is the uploadToS3 function:
var uploadToS3 = function(filename, s3url, fileData) {
var xhr = createCORSRequest('PUT', s3url);
if(!xhr) {
console.log('CORS not supported');
error();
return;
}
xhr.onload = function () {
if(xhr.status == 200) {
console.log('100% - Upload completed.');
callback(filename); //callback defined in outer context
}
else {
console.log('0% - Upload error: ' + xhr.status);
console.log(xhr.responseText);
error();
}
};
xhr.onerror = function () {
console.log(0, 'XHR error.');
error();
};
xhr.upload.onprogress = function (e) {
if(e.lengthComputable) {
var percentLoaded = Math.round((e.loaded / e.total) * 100);
var label = (percentLoaded == 100) ? 'Finalizing.' : 'Uploading.';
console.log(percentLoaded + "% - " + label);
}
};
xhr.setRequestHeader('Content-Type', "image/png");
//xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.send(fileData);
};
EDIT:
I checked the filesize by logging evt.target.result.byteLength and it was ok, so evt.target.result contains image data. Still there is a problem with the upload - I checked the s3 storage and file size is 0, so I am not constructing the Blob correctly.
So this is an android bug after all, which was not fixed since at least Nov 2012.
Here is an article I found which is directly related to my problem: https://ghinda.net/article/jpeg-blob-ajax-android/
It also provides a workaround for the bug, which is to send ArrayBuffer directly, without creating a Blob. In my case I had to send evt.target.result directly.