I have a curl command that I want to adapt to javascript using ajax.
curl -v -X 'POST' --data-binary #BinaryData.bin.txt "http://127.0.0.1:3000/api/v1/update_data"
In javascript I used FileReader() and read the file as Text, BinaryString, Array Buffer with different ajax params settings for processData, contentType, cache, etc several times but did not succeed in sending the proper binary string like in python example below.
I tried doing it in python and the following code seems to work as intended:
import requests
import os
path = os.path.normpath('d:/BinaryData.bin.txt')
file = open(path, 'rb')
data = file.read()
r = requests.post("http://127.0.0.1:3000/api/v1/update_data", data=data)
What am I missing in Javascript that it doesn't seem to send the correct data from this file?
Example of how I tried doing it in javascript:
onFileSelected: function(evt) {
var file = evt.target.files[0];
var reader = new FileReader();
reader.onload = (function (file) {
return function(e) {
var data = e.target.result;
$.ajax({
url: "http://127.0.0.1:3000/api/v1/update_data",
data: data,
contentType: 'application/octet-stream',
processData: false,
type: "POST",
success: function () {
// all good
},
error: function() {
// failed
}
});
}
reader.readAsBinaryString(file);
}
Related
I have a C# Rest API method which accepts System.IO Stream object as argument and I am trying to pass a file to this C# method as a file stream using Ajax call. Please suggest how to do this? I tried two ways-
Creating FormData object in JavaScript and
Creating File object in JavaScript.
C# method
[WebInvoke(UriTemplate = "/{businessObjectId}/uploadAttachment?filename={filename}&caption={caption}")]
public Message UploadAttachment(string filename, string caption, Stream stream, string businessObjectId){....}
Ajax Method
$("input[name*='btnUpload']").live("click", function () {
addGlobalAttachment();
});
function addGlobalAttachment() {
var fileData = $("input[id*='fileUpload']");
var fileName = fileData[0].files[0].name;
var fileCaption = $("input[name*='txtFileCaption']").val();
var friendlyID = $(".order").html();
var fileInput = new File(fileData[0].files, fileName, { type: "text/plain", lastModified: Date(0) });
var URL = "http://localhost:62059/Order/" + friendlyID + "/uploadAttachment?filename=" + fileName + "&caption=" + fileCaption;
$.ajax({
type: 'POST',
url: URL,
data: fileInput,
processData: false,
contentType: 'application/octet-stream',
success: function (attachmentResult) {
debugger;
}
},
error: function (result) {
}
});
}
I have a very simple task that just needs to upload a file and have the AJAX post it to the Index page:
<input type="file" id="file-selector" accept=".txt">
Associated Javascript:
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
const file = event.target.files[0];
const reader = new FileReader();
reader.addEventListener('load', event => {
const txtFile = event.target.result;
$.ajax({
type: "POST",
url: "/ControlData?handler=FileUploader",
error: function (request, status, error) { alert(request.responseText); },
data: txtFile,
cache: false,
contentType: false,
processData: false,
headers: { "RequestVerificationToken": "#token" }
});
});
reader.readAsText(file);
});
Code in /Pages/ControlData/Index.cshtml.cs:
public IActionResult OnPostFileUploaderAsync(IFormFile model)
{
return null;
}
The app runs fine, the file is selected, but the POST call always gets a 404:
The app runs fine, the file is selected, but the POST call always gets a 404
Please check if you configured page route with route data parameter, like #page "{title}" etc, which cause HTTP 404 error.
https://learn.microsoft.com/en-us/aspnet/core/razor-pages/razor-pages-conventions?view=aspnetcore-5.0#configure-a-page-route
https://www.learnrazorpages.com/razor-pages/routing#route-templates
needs to upload a file and have the AJAX post it to the Index page
Code in /Pages/ControlData/Index.cshtml.cs
public IActionResult OnPostFileUploaderAsync(IFormFile model)
To post selected file to your handler OnPostFileUploaderAsync, you can try modify the code like below.
<script>
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
const file = event.target.files[0];
//post the selected file through formdata
//instead of using the readAsText() method to read the contents of the specified file
var txtFile = new FormData();
txtFile.append("model", file);
$.ajax({
type: "POST",
url: "/ControlData/Index?handler=FileUploader",
error: function (request, status, error) { alert(request.responseText); },
data: txtFile,
cache: false,
contentType: false,
processData: false,
headers: { "RequestVerificationToken": "#token" }
});
});
</script>
Test Result
Problem:
I have a situation where I'd like to upload a file (pdf, image, etc.) to an API Endpoint that accepts one of these types of files. However, the file is located on another web service somewhere. I'm trying to devise a clever solution that will allow me to (a) download the remote file (and store it as bytes in memory or something) then (b) upload that file through the API.
I have jQuery code that demonstrates how to upload a local file using jQuery with no backend code, but I'd like to extend it to allow me to upload something that is stored remotely.
Constraints:
I don't want to use any backend infrastructure on my image uploading page (ie. no php, python, ruby, etc.)
I don't want the end user of my form to need to download the file to their machine and upload the file as a two-step process.
What I've got so far:
I've seen some solutions on SO that kind-of connect the dots here in terms of downloading a file as a bytearray, but nothing that demonstrates how you might upload that.
Download File from Bytes in JavaScript
jQuery-only File Upload to Stripe API*
Keep in mind, Stripe is the example I have, but I'd like to try and replicate this on say Imgur or another API (if I can get this working). Hopefully someone else has some ideas!
$('#fileinfo').submit(function(event) {
event.preventDefault();
var data = new FormData();
var publishableKey = 'pk_test_***';
data.append('file', $('#file-box')[0].files[0]);
data.append('purpose', 'identity_document');
$.ajax({
url: 'https://uploads.stripe.com/v1/files',
data: data,
headers: {
'Authorization': 'Bearer ' + publishableKey,
// 'Stripe-Account': 'acct_STRIPE-ACCOUNT-ID'
},
cache: false,
contentType: false,
processData: false,
type: 'POST',
}).done(function(data) {
$('#label-results').text('Success!');
$('#upload-results').text(JSON.stringify(data, null, 3));
}).fail(function(response, type, message) {
$('#label-results').text('Failure: ' + type + ', ' + message);
$('#upload-results').text(JSON.stringify(response.responseJSON, null, 3));
});
return false;
});
I actually got this working for Stripe by doing this:
https://jsfiddle.net/andrewnelder/up59zght/
var publishableKey = "pk_test_xxx"; // Platform Publishable Key
var stripeAccount = "acct_xxx"; // Connected Account ID
$(document).ready(function () {
$('#file-upload').on('submit', function (e) {
e.preventDefault();
console.log('Clicked!');
var route = $('#file-route').val(); // URL OF FILE
var fname = route.split("/").slice(-1)[0].split("?")[0];
var blob = fetchBlob(route, fname, uploadBlob);
});
});
function fetchBlob(route, fname, uploadBlob) {
console.log('Fetching...')
var oReq = new XMLHttpRequest();
oReq.open("GET", route, true);
oReq.responseType = "blob";
oReq.onload = function(e) {
var blob = oReq.response;
console.log('Fetched!')
uploadBlob(fname, blob);
};
oReq.send();
}
function uploadBlob(fname, blob) {
var fd = new FormData();
fd.append('file', blob);
fd.append('purpose', 'identity_document');
console.log('Uploading...');
$.ajax({
url: 'https://uploads.stripe.com/v1/files',
data: fd,
headers: {
'Authorization': 'Bearer ' + publishableKey,
'Stripe-Account': stripeAccount
},
cache: false,
contentType: false,
processData: false,
type: 'POST',
}).done(function(data) {
console.log('Uploaded!')
}).fail(function(response, type, message) {
console.log(message);
});
}
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
I am using the Dropbox Core API to upload and download files via a chrome extension. When I upload text files such as with extensions .txt, .js, .json or .c the files get uploaded successfully but when I upload files with extensions .pdf, .jpg etc (media files) then the contents are disfigured or absent, though the file size is non-zero, sometimes even larger than the original file. This clearly means that the data that is read is being written as well but I guess there is some problem with the way I am reading or writing the data. The code is posted below for reference.
$(document).on("click", "#id_submit",uploadProcess);
function uploadProcess()
{
var file = $("#upload_file")[0].files[0];
console.log(file);
if (!file){
alert ("No file selected to upload.");
return false;
}
var reader = new FileReader();
//reader.readAsText(file, "UTF-8");
reader.readAsBinaryString(file);
reader.onload = function (evt) {
uploadFile(file.name, evt.target.result, file.size, file.type);
//console.log(evt.target.result);
var control = $("#upload_file");
control.replaceWith( control = control.clone( true ));
}
}
//function to upload file to folder
function uploadFile(filepath,data,contentLength,contentType){
var url = "https://api-content.dropbox.com/1/files_put/auto/"+filepath;
var headers = {
Authorization: 'Bearer ' + getAccessToken(),
contentLength: contentLength
}
var args = {
url: url,
headers: headers,
crossDomain: true,
crossOrigin: true,
type: 'PUT',
contentType: contentType,
data : data,
dataType: 'json',
success: function(data)
{
console.log(data);
},
error: function(jqXHR)
{
console.log(jqXHR);
}
};
$.ajax(args);
}
You can actually pass a file in your ajax request(depending on browser support). Just pass the files in your args object, also you need to set processDate and contentType to false to prevent $.ajax from manipulating the file object
var args = {
...
contentType: false,
data : file,
processData: false,
...
};