I want to upload a file with the following API request using HTTPS module and a POST request
I wrote the following code to upload a file
function upldoad_file_greater_150_MB(fileid, path_to_upload, filename) {
try {
var _url = DROPBOX_URL_V2 + _UPLOAD_150_MB_FILE
var _headers = {
'Content-Type': 'application/octet-stream',
'Authorization':'Bearer ' + ACCESS_TOKEN,
'Dropbox-API-Arg' : JSON.stringify({ 'path': path_to_upload + '/' + filename })
}
var responseDB = https.post({
url: _url,
headers: _headers,
body: file.load({id: fileid})
});
if (responseDB.code != 200)
log.audit({ title: 'Request Failed', details: responseDB })
if (responseDB.code == 200)
log.audit({ title: 'Request Succeed', details: responseDB })
} catch (error) {
log.error('fileid : ' + fileid, error)
}
}
As expected the file is correctly created in Dropbox (right path and filename) but as expected the content is absolutely not correct.
I spent a lot of time looking through different articles to understand and find a way to properly upload a file, but I didn't find anything other than this
In NetSuite with SuiteScript 2.0 unable to send a file with HTTP POST request with a content-type multipart/form-data
But It doesn't work in my case
Related
I am trying to upload a file to the server and the server APIs are written using django. The file upload is working perfectly from Postman but when i try to upload from mobile app (React Native) using axios the backend is not able to read it.
Following is the Frontend Snippet:
let accessToken = await AsyncStorage.getItem('accessToken')
let formData = new FormData()
formData.append('doc_type', this.state.selectedDoc.id)
formData.append('document', this.state.selectedFiles) // <- This is the fetched file in array format . [{filname:'abc', size:12344,.....}]
formData.append('description', this.state.description.value)
formData.append('data', JSON.stringify(this.state.selectedDoc.fields))
let url = `${AppConstants.url}api/${AppConstants.apiVersion}/upload_doc`
var config = {
method: 'post',
url: url,
data: formData,
headers: {
'Authorization': `Bearer ${accessToken}`,
}
}
axios(config)
.then((resp) => {
resolve(resp)
})
.catch((err) => {
reject(err)
});
And the backend-end if else statement is as follows:
if(request.FILES.getlist("document")):
files = request.FILES.getlist("document")
....
....
....
else:
return response.JsonResponse({
'success' : False,
'message' : 'Please Upload a file'
}, status = status.HTTP_200_OK)
The above else block is executed even though the UI is sending a valid file.
Request you to please share a solution.
I have a REST API developed using Play Framework/Java and front end developed in Angular JS.
I am trying to call a POST method fron the Angular Client to the server using the following code:
$scope.login = function () {
console.log('login called');
var loginURL = 'http://localhost:9000/login';
var loginInfo = {
'email': $scope.email,
'password': $scope.password
};
$http({
url: loginURL,
method: 'POST',
data: loginInfo,
headers: { 'Content-Type': 'application/json' }
}).then(function (response) {
console.log('SUCCESS: ' + JSON.stringify(response));
$scope.greeting = response.status;
}, function (response) {
console.log('ERROR: ' + JSON.stringify(response));
});
}
This is the code at my server:
public Result doLogin() {
ObjectNode result = Json.newObject();
result.put("status", "success");
return ok(result).withHeader("Access-Control-Allow-Origin", "*");
}
And this is the application conf file:
#allow all hosts.
play.filter.hosts {
allowed = ["."]
}
#allow CORS requests.
play.filters.cors {
allowedOrigins = ["*"]
}
Yet even after enabling CORS, I am getting error in console in both Firefox and Google Chrome:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:9000/login. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
ERROR: {"data":null,"status":-1,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"http://localhost:9000/login","data":{"email":"xxx","password":"xxx"},"headers":{"Content-Type":"application/json","Accept":"application/json, text/plain, /"}},"statusText":""}
I do know that the server is sending the correct response and the correct header because when I do the POST from Postman, I can see the response and also the headers containing {"Access-Control-Allow-Origin", "*"} in Postman.
So then, what could be the problem? Is there something I am missing from the Client side?
The difference between POSTMAN request and browser request is browser sends an OPTIONS request before the actual POST / GET request.
To be able to accept OPTION request with your play framework allowedHttpMethods = ["GET", "POST" ,"OPTIONS"]
for follow this link
Play Framework 2.3 - CORS Headers
This causes a problem accessing CORS request from a framework (like angularjs). It becomes difficult or the framework to find what was the options request for and take action properly.
For fixing your problem you will need to analyze how the options request going and how it's being interpreted and how to overcome. But in general, I suggest using "fetch" built-in request for this, which supports the promises so can be chained easily with angularjs code
so your code will look something like this
$scope.login = function () {
console.log('login called');
var loginURL = 'http://localhost:9000/login';
var loginInfo = {
'email': $scope.email,
'password': $scope.password
};
fetch(loginURL, {
method: 'post',
headers: {
"Content-type": "application/json"
},
body: loginInfo
}).then(function (response) {
console.log('SUCCESS: ' + JSON.stringify(response));
$scope.greeting = response.status;
}, function (response) {
console.log('ERROR: ' + JSON.stringify(response));
});
}
I built a Ruby/Sinatra backend for an angularjs app. I wrote a POST call to parse and upload a file from the request body to AWS S3. Now when I use Postman to upload a file. It works completely fine, the file gets uploaded and I can view it on S3. But the problem is that when I try to upload a file using the angular app, it adds the following to the file cause of which the file gets corrupted and a pdf file opens up as a text file within the browser.
------WebKitFormBoundaryuRzuSgC6oXxEgwa1
Content-Disposition: form-data; name="file"; filename="Application Form.pdf"
Content-Type: application/pdf
***FILE DATA HERE***
------WebKitFormBoundaryuRzuSgC6oXxEgwa1--
Can someone help me to either parse this data properly in the ruby or help me to avoid adding this extra code from the angular app.
This is the angular code to upload the file
$scope.uploadFiles = function(files, errFiles) {
$scope.all_files.push(files);
console.log($scope.all_files[0]);
$scope.files = files;
$scope.errFiles = errFiles;
angular.forEach(files, function(file) {
file.upload = Upload.upload({
url: 'http://api.company.com/upload',
data: {file: file}
});
file.upload.then(function (response) {
$timeout(function () {
file.result = response.data;
});
}, function (response) {
if (response.status > 0)
$scope.errorMsg = response.status + ': ' + response.data;
}, function (evt) {
file.progress = Math.min(100, parseInt(100.0 *
evt.loaded / evt.total));
});
});
};
And the following is the code in Ruby to parse and upload the file
post '/upload' do
request.body.rewind
body = request.body.read
res(200, {url: saveFile(body)})
end
def saveFile(body)
name = "random string here"
s3 = Aws::S3::Resource.new(region:'ap-southeast-1')
obj = s3.bucket('company-files').object(name)
obj.put(body: body, acl:'public-read')
saved_url = obj.public_url
return saved_url
end
You may need to manually set the Content-Type header to force your browser to use this upload mechanism, probably at this point:
file.upload = Upload.upload({
url: 'http://api.company.com/upload',
data: {file: file}
});
I don't know what's Upload object, so I can't say how to do it
here is the situation.
I have an angular app that need to be used via a machine on wich you can put an USB key.
Several exports are possible from the corresponding backend and thoses exports (pdf, csv or rtf) need to be downloaded directly on the key, without asking the user.
Furthermore I need to be able to detect if the key is not present and show an error.
I don't think that it is doable using only angular with chromium.
I was thinking of making a local nodejs server on each machine that could access the filesystem for that. It works when using postman with form-data, but I don't know how I can pass a file donwloaded in angular to the nodejs server as a formdata, I keep getting incorrect pdf files.
TLDR :
I need to be able to have a chain like this :
get file from backend in angular
post a request to local (nodejs) server with the downloaded file
receive the file in nodejs to save it on disk
I am open to other ideas if this one doesn't work, as long as I can download this file I am happy.
current nodejs code, that works when i post the file using postman :
router.post('/save', function(req, res, next) {
console.log('savexvbxc');
var fstream;
//test if USB key is available
fs.stat(basePath, function(err, stats) {
if (err) {
console.log('error, key not present');
res.send(412, 'FAILURE');
}
var filename = basePath + 'toti.pdf';
console.log('filename is ' + filename);
if (req.busboy) {
console.log('busboy loaded');
req.busboy.on('file', function(fieldName, fileStream, fileName, encoding, mimeType) {
console.log('Saving: ' + filename + ' ' + fileName);
fstream = fs.createWriteStream(filename);
fileStream.pipe(fstream);
fstream.on('close', function() {
console.log('successfully saved ' + filename);
res.status(200).send('SUCCESS');
});
fstream.on('error', function(error) {
console.log('failed saved ' + filename);
console.log(error);
res.send(500, 'FAILURE');
});
});
req.busboy.on('error', function(error) {
console.log('failed saved ' + filename);
console.log(error);
res.send(500, 'FAILURE');
});
return req.pipe(req.busboy);
} else {
console.log('error, busboy not loaded');
res.send(500, 'FAILURE');
}
});
});
current angular code that do not work:
var dlReq = {
method: 'GET',
url: '/fep/documents/TVFI_FEP_0015_SFS_Specifications_Fonctionnelles_Detaillees_V00.9.pdf',
headers: {
'Content-Type': 'application/pdf',
'Accept': 'http://localhost:4000/fep/documents/TVFI_FEP_0015_SFS_Specifications_Fonctionnelles_Detaillees_V00.9.pdf'
},
responseType: 'arraybuffer'
};
$http(dlReq).then(function(data, status, headers, config) {
console.log(resp);
var file = new Blob([(resp)], {type: 'application/pdf'});
var formdata = new FormData();
formdata.append('file', file);
var request = {
method: 'POST',
url: 'http://localhost:4080/save',
data: formdata,
headers: {
'Content-Type': undefined,
'Accept': '*/*'
}
};
// SEND THE FILES.
$http(request)
.success(function(d) {
console.log('ok', d);
})
.error(function() {
console.log('fail');
});
});
Thank you
i've got an Application based on NodeJS and AngularJS and pushed it to openshift. But everytime i try to upload something, i get the following error:
POST http://www.domain.de/api/upload/file 502 (Bad Gateway)
Angular sends the data like this:
$scope.newFile = function() {
$scope.id = $scope.group._id;
var fd = new FormData();
var file = $scope.files[0];
fd.append('file', file);
if (file.type!="application/pdf"){
mvNotifier.error("Nur PDF Dateien sind akzeptiert.");
return;
}
$http.post('/api/upload/file', fd, {
transformRequest: angular.identity,
headers:{'Content-Type': undefined}
})
.success(function(d) {
var data = {
name: file.name,
description: $scope.descriptionfile
}
mvNotifier.notify("Bis hier hin klappt alles");
console.log("sucess on uploading ");
mvFactory.POST(data, mvGroup, {_place:"file", _id:$scope.id}).then(function(data) {
$scope.newfile=false;
$scope.group.files.push({name:file.name, description:$scope.descriptionfile});
mvNotifier.notify("Datei hochgeladen");
}, function(reason) {
mvNotifier.error("reason");
})
})
.error(function(data,status,header) {
mvNotifier.error("Upload hat nicht funktioniert.")
console.log("data", data);
console.log("status", status);
console.log("header", header);
})
And the Server routes to a file using busboy to save it:
uploadFile: function(req,res) {
console.log("req",req.files);
if (process.env.OPENSHIFT_DATA_DIR!= undefined) {
var cPath = process.env.OPENSHIFT_DATA_DIR;
} else {
var cPath = path.resolve('..', 'data');
}
var busboy = new Busboy({ headers: req.headers });
req.pipe(busboy);
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
var wPath = cPath + '/uploads/documents';
file.pipe(fs.createWriteStream(wPath + '/' + filename));
file.on('end', function() {
console.log('File [' + fieldname + '] Finished');
});
});
busboy.on('finish', function() {
console.log('Done parsing form!');
});
res.status(200).end();
}
On Localhost everything is working just fine and the data is saved to the server. but i get the response of bad gateway and this header:
<title>502 Bad Gateway</title>
</head><body>
<h1>Bad Gateway</h1>
<p>The proxy server received an invalid response from an upstream server.<br />
Can someone help me please?
I've resolved the issue. I post it so that someone who has the problem can solve it to.
The Web load balancer at openshift is HAproxy and has issues with the upload because the response of the server wasn't identical with the request because of the content type. I switched from $http from angular to an XHR. That solved the issue and works fine. The content-type i didn't set at all. now it works fine.