Node.js POST request with multipart file as parameter - javascript

I need to issue a POST request in Node.js to an API which takes two parameters: 1) "metadata", a string, and 2) "file", a multipart file.
The following is part of the server-side java code:
public ResponseEntity<CmisDocumentDTO> createDocument(
#ApiParam(name = "file", value = "File to be uploaded.", required = true) #RequestParam("file") MultipartFile file,
#ApiParam(name = "metadata", value = "Metadata of the document", required = false) #RequestParam("metadata") String metadata) {
//Calls the service
}
The following is my node.js code calling this request. The file is on my local machine and uses the form-data module:
var FormData = require('form-data');
var form = new FormData();
form.append("metadata", "metadata_string_goes_here");
form.append("file", fs.createReadStream(fileName));
var request = https.request({
method: 'post',
host: 'example.org',
path: '/upload',
"rejectUnauthorized": false,
headers: form.getHeaders()
});
form.pipe(request);
request.on('response', function(res) {
console.log(res.statusCode);
});
When I run this code, an internal service error (code: 500) is returned that says the MultipartFile parameter "file" is not present.
How do I successfully submit a POST request with a multipart file as a parameter?
Thanks!

fileName should be path of the file in local machine
fs.createReadStream(fileName)
In case you have not given absolute path starting with root then Relative paths work, but they are relative to process.cwd(), not the currently executing module.

Related

Why is node.js not generating an email with guerrillamail?

I am writing code that creates an email address with guerrillamail.
But, the code I created below:
var request = require('request');
var jar = request.jar();
request({
uri: 'http://api.guerrillamail.com/ajax.php',
method: 'GET',
proxy: proxy,
jar: jar,
form: {
"f": "get_email_address"
}
}, function(e, response, b) {
console.log(b);
});
Only logs :
ERR_INVALID_REQ
In body when I log it. How can I get this to work?
probably need a POST request not GET try changing the method

how to add more than one object to FormData

I am able to upload an image just fine. However, I need to send a json object with the image so that I can identify what record the image belongs to. What am I doing wrong? Why does the variable info come through as null on the java side of the service?
Client:
let file = event.target.files[0];
let info = {formId:8, formVersionId:2, formIndex:0};
var formData = new FormData();
formData.append('file', file);
formData.append('info', info );
$.ajax({
url: URL.BUILDER_URL + '/megaUpload',
type: 'POST',
data : formData,
cache : false,
contentType : false,
processData : false,
});
server:
public Response uploadFile( #FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail,
#FormDataParam("info") GuiCreateResponse info) {
}
https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
Here it clearly states that ,
FormData value can either be a string or a blob.
let file = event.target.files[0];
var formData = new FormData();
formData.append('file', file);
formData.append('formId', '8' );
formData.append('formVersionId', '2' );
formData.append('formIndex', '0');
This should solve your issue.
You are using formId, but you likely want to surround it in quotes as "formId". Try this code.
let file = event.target.files[0];
let info = {"formId":8, "formVersionId":2, "formIndex":0}; //See changes here
var formData = new FormData();
formData.append('file', file);
formData.append('info', info );
$.ajax({
url: URL.BUILDER_URL + '/megaUpload',
type: 'POST',
data : formData,
cache : false,
contentType : false,
processData : false,
});
Maybe this is your issue. The docs say, "When using the append() method it is possible to use the third optional parameter to pass a filename inside the Content-Disposition header that is sent to the server. When no filename is specified (or the parameter isn't supported), the name "blob" is used."
Since you do not provide a third parameter, I'm thinking the FormDataContentDisposition needs to look for "blob". Try changing your server annotations to check for that name:
public Response uploadFile( #FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("blob") FormDataContentDisposition fileDetail,
#FormDataParam("info") GuiCreateResponse info)

get file from filepath in javascript

I want to send my form(which will have file and name in it) using javascript to the server using http.post request but I am not able to fetch file in javascript. How will i do that i have file path. And i don't want to do this using input tag.
var Form = new FormData();
Form.append("file", file);//this file has to added using path of the file
$http.post(url, Form, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
})
.success(function(d) {
console.log("sucess" + d);
});

Azure Blob Image Upload 405 (The resource doesn't support specified Http verb)

I am attempting to upload an image (an HTML5 canvas converted to an image which is working as intended) to Azure Blob Storage using JavaScript. At this stage, I am less concerned with file size and most concerned with being able to post the file to Azure Blob Storage. I have read a lot of different articles about SAS and for the intents of testing I have a public container, but need to learn how to generate SAS. At this point, I just need to be able to post. I have configured my blob account with CORS as follows:
Allowed Origins: http://localhost:50045
Allowed Methods: DELETE,GET,NONE,POST,PUT
Allowed Headers: content-length,accept,x-ms-*
Exposed Headers: x-ms-*
Max Age (seconds): 10000
When I use the following upload code, which is working to upload to a separate vendors Web Service, I get the following error:
405 (The resource doesn't support specified Http Verb.)
Here is my code:
$scope.reRender = function () {
var canvasImage = document.getElementById("c");
var img = canvasImage.toDataURL("image/png");
var filename = 'Test';
var formdata = new FormData();
formdata.append(filename, img);
var send = function (blob) {
var filename = 'Test.png';
var formdata = new FormData();
formdata.append('File1', blob, filename);
$.ajax({
url: 'http://myblobaccount.blob.core.windows.net/blob1',
type: "POST",
data: formdata,
mimeType: "multipart/form-data",
processData: false,
contentType: false,
crossDomain: true,
success: function (result) {
console.log("Upload to Azure complete!");
},
error: function (error) {
console.log("Something went wrong!");
}
})
}
var canvasImage = document.getElementById("c");
if (!canvasImage.toBlob) {
var dataURL = canvasImage.toDataURL();
var bytes = atob(dataURL.split(',')[1])
var arr = new Uint8Array(bytes.length);
for (var i = 0; i < bytes.length; i++) {
arr[i] = bytes.charCodeAt(i);
}
send(new Blob([arr], { type: 'image/png' }));
}
else
canvasImage.toBlob(send);
}
Does Azure Blob Storage not support a POST? Or is my upload code not in alignment with what Azure is looking for to POST the image file into "blob1"?
Azure blob storage does not support HTML form based file upload, AWS S3 supports this. So POST is not supported by Azure Blob storage. I think it supports PUT, you can try PUT.
But doing all this in JavaScript is dangerous, anyone can put items after acquiring necessary shared signature. If you are not providing shared access signature, blob storage will not allow any operation at all.
Instead you must upload file to your server, PHP, ASP or anything and then connect to Azure via its SDK and save it. Or create a shared signature with rights.
You must get SASToken and add it to your path,
use type: "PUT",
use headers: [{ name: 'x-ms-blob-type', value: 'BlockBlob' }]
Something like this:
<code>
import { Injectable } from '#angular/core';
import { FileUploader, FileItem, Headers } from 'ng2-file-upload';
import { Http } from '#angular/http';
#Injectable()
export class Uploader {
public uploader: FileUploader = new FileUploader({ url: URL, method: 'PUT' });
public hasBaseDropZoneOver: boolean = false;
public files: FileItem[] = this.uploader.queue;
public r: Response;
constructor(private httpClient: Http){}
public getUploader(): FileUploader {
return this.uploader;
}
public fileOverBase(e: any): void {
this.hasBaseDropZoneOver = e;
}
public uploadAll(): void {
this.httpClient.get(getToken)
.subscribe(
result => {
if (result.ok) {
for (var n = 1; n <= this.files.length; n++) {
let fullUrl = URL + this.files[n].file.name + result.json();
console.log('--> send url ' + fullUrl);
this.uploader.setOptions({
url: fullUrl, method: 'PUT',
headers: [{ name: 'x-ms-blob-type', value: 'BlockBlob' }]
});
this.uploader.uploadItem(this.files[n]);
}
}
else {
console.log('--> get token error ' + result.statusText);
}
});
}
public cancelAll(): void {
this.uploader.cancelAll();
}
public clearQueue(): void {
this.uploader.clearQueue();
}
}
</code>
The below is my CORS properties setting which work to me, hope this will be helpful.
Allowed Origins: *
Allowed Methods: GET,PUT
Allowed Headers: *
Exposed Headers: *
Max Age (seconds): 200

Downloading Excel file xlsx in Angularjs and WebApi

I am working on a task, in which I have to download a report in xlsx format. The report file is generated successfully from server, and is received on client side as well. But it is not opening and producing invalid format error.Below is the code of server side.
var output = await reportObj.GetExcelData(rParams);
if (output != null){
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(output.ConentBytes)
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = output.FileName
};
return result;
}
Here is the code for client side:
var saveData = function (response) {
if (response.status === 200) {
var reportData = response.data;
var b = new Blob([reportData], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
saveAs(b,"ReportFile.xlsx");//this is FileSaver.js function
} else {
console.log(response.statusText);
}
};
$scope.getExcelFile = function(reportName, reportParams) {
reportDataService.getExcelReportData(reportName, reportParams, saveData);
}
Below is the error message:
Excel could not open newFile.xlsx because some content is unreadable. Do you want to open and repair this workbook?
On clicking repair, following error appears:
Excel cannot open this file.
The file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.
Can some one guide me what I am doing wrong? Meanwhile, the same server side file generator objects works smoothly in ASP.Net forms application, and the file opens without any error as well.
Thank you.
I expect your $http call is missing the response type configuration. This is the way I download office files:
function download(url, defaultFileName) {
var self = this;
var deferred = $q.defer();
$http.get(url, { responseType: "arraybuffer" }).then(
function (data, status, headers) {
var type = headers('Content-Type');
var disposition = headers('Content-Disposition');
if (disposition) {
var match = disposition.match(/.*filename=\"?([^;\"]+)\"?.*/);
if (match[1])
defaultFileName = match[1];
}
defaultFileName = defaultFileName.replace(/[<>:"\/\\|?*]+/g, '_');
var blob = new Blob([data], { type: type });
saveAs(blob, defaultFileName);
deferred.resolve(defaultFileName);
}, function (data, status) {
var e = /* error */
deferred.reject(e);
});
return deferred.promise;
}
I was facing the same error , content was in hexa format, so i added a response type as arraybuffer, problem got resolved. please see below.
$http({
url: '/api/sendPMOToBackendUpdate',
method: "POST",
headers: {'Content-type': 'application/json'},
data: backendTsData,
responseType: 'arraybuffer'
}).success(function(data, status, headers){
var file = new Blob([ data ], { type : 'application/vnd.ms-excel'});
var defaultFileName ="TSC-"+$scope.user.name+"-"+$scope.user.ohrId+".xls";
saveAs(file,defaultFileName);
}).error(function(err) {
console.log('Error: ' + err);
});
You a just need to do one thing only that.
include following js to save file locally. Download it from
"https://github.com/eligrey/FileSaver.js/"
your response data should be in blob type.
I have implemented it and its working.
function downloadfile(url,defaultFileName){
var self = this;
var deferred = $q.defer();
$http.get(url, { responseType: "blob" }).then(
function (data){
saveAs(data.data, defaultFileName)
deferred.resolve(defaultFileName);
}, function (data) {
var e = /* error */
deferred.reject(e);
});
return deferred.promise;
}
I encountered a similar problem when writing excel using Javascript library Excel Builder. At the end, I found the reason was that a control character '\u001a' was included in data.
The solution is to encode the control char in Excel's way as '_x001a_'.
The way I diagnosed the problem was like this:
.xlsx file is just a zipped xml file. You can open it with 7-zip. Inside the xl/ folder there is a file sharedString.xml containing all strings. Extract the file and open it with Notepad++. If you see any control character, then it might be the cause.
first install these module
import * as Excel from 'exceljs';
import * as fs from 'file-saver';
In your function write these
const workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet('sheet');
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 }
];
var buff = workbook.xlsx.writeBuffer().then(function (data) {
var blob = new Blob([data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
fs.saveAs(blob, "publications.xlsx");
});
Fs is used to access file system and download file. You can also insert img
https://www.npmjs.com/package/exceljs#images

Categories