Write to file while stream downloading - javascript

How to write output of an octet-stream to a file while the stream is being downloaded ?
I receive the stream as a blob and then download it at the end of the stream, but how to receive the
stream and write to a file ?(something like a FileStream that takes a stream and writes to a file)
AJAX code below
$.ajax({
type: "post",
url: apiURL,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(String(strCustomData)),
xhrFields: {
responseType: "blob", // <-- can also be an arrayBuffer
onprogress: function(e) { // <-- get response body here, read its stream and save in file
// TODO
}
},
cache: false,
headers: { "RequestVerificationToken": get_CSRF_TOKEN() },
success: function (response, textStatus, request) {
const requestHeaders = request.getResponseHeader("Content-Disposition") || "";
const requestContentType = request.getResponseHeader("Content-Type") || "application/zip";
const strFileName = requestHeaders?.split(";")[1]?.split("=")[1] || "File_Not_Found.zip";
const blob = response;
const url = window.URL || window.webkitURL;
const urlLink = url.createObjectURL(blob);
// create Anchor element that holds the blob and then download it as a file
const elementAnchor = document.createElement("a");
elementAnchor.setAttribute("href", urlLink);
elementAnchor.setAttribute("download", strFileName);
// download the file
elementAnchor.click();
// dispose blob object and delete it from memory
url.revokeObjectURL(urlLink);
elementAnchor.remove();
},
error: function (xhr, ajaxOptions, thrownError) {
// More validation code...
console.error(String(xhr.statusText));
}
});
I am looking for something like the anchor download tag <a asp-page-handler="apiURL" download>Download</a> where it receives a stream and downloads its without using a blob.
I would have used the anchor tag, but I need some Javascript code to be executed alongside it.(Progress bar, some required custom info to display, ...etc.)
I tried using StreamSaver.js but could not make it work in the onprogress section of the AJAX request.(how to get the response.body.getReader() in onprogress event ?how to save stream to a file without waiting for the download to complete ?)
Using JQuery inside Razor pages with Asp.Net Core.

Related

Get .wav blob from url

I'm trying to get a blob from an URL (in my case leads to a .wav file).
The URL is located at my own website, so I only do requests to the same site.
The purpose:
A user has uploaded some .wav files to my website to one schema
The user wants to copy one or more .wav files from one to another schema
The user selects the audiofiles to copy without uploading the files again.
The user interface looks like this:
The problem:
Each audiofile is located in its own directory.
https://mywebsite.nl/media/audiofiles/schemaGUID/recording.wav
So when copying to another schema, the file or files needs to get re-uploaded to the directory of the other schema.
The code im using to upload the selected audiofiles is this:
newwavfiles.forEach(function (item) {
var name = item["name"];
var filename = item["filename"];
var fileblob = fetch('http://mywebsite.nl/media/audiofiles/12345677/recording.wav').then(res => res.blob());
var formData = new FormData();
formData.append('file', fileblob, filename);
formData.append('guid', guid);
// upload file to server
$.ajax({
url: 'index.php?action=uploadAudiofile',
type: 'post',
data: formData,
enctype: 'multipart/form-data',
contentType: false,
processData: false,
success: function (response) {
},
error: function (xhr, status, error) {
console.log(xhr);
var errorMessage = xhr.status + ': ' + xhr.statusText
}
});
});
To get the blob of the file I tried this:
var fileblob = fetch('http://mywebsite.nl/media/audiofiles/12345677/recording.wav').then(res => res.blob());
But then I get this error:
Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'.
Does anyone have a solution to get the .wav file blob from an URL?

jQuery AJAX response coming as string blob

I am calling AWS S3 to retrieve images using AJAX call in jQuery 3.3.0 and instead of getting a blob object, I am receiving the response as "[object Blob]". Please let me know if I have to provide further details.
Please find the code below:
$.ajax({
url: "my_path/download_image.php",
data: {
name: "my_name"
},
cache: false,
xhrFields: {
responseType: 'blob'
},
success: function (data) {
console.log(data);
var image = new Image();
var url = window.URL || window.webkitURL;
self.DownloadStudentImages(students, index + 1);
image.src = url.createObjectURL(data);
self.SavePic(imageFilename);
},
error: function () {}
});
I have fixed the issue. Usually, AWS response from PHP is in string format unless it is encoded explicitly. So, I am sending base64 from PHP and in the javascript side, I am converting it to a byte array and thus into a blob which fixes the issue.

Google Cloud Functions HTTP unable to successfully POST content type application/octet-stream

I'm trying to write a Google Cloud Functions HTTP handler to upload audio files constructed as blobs to Google Cloud Storage from a webpage. Based on the documentation linked above I want the body of my POST request to be handled as a Node.js Buffer and I can achieve this with Content-Type: application/octet-stream. I'm sending the request from a webpage that has this xhr request:
// where `var blob` is a Blob of type "audio/wav"
// and size of > 0 generated from the
// WebAudioAPI
var fileReader = new FileReader();
fileReader.onloadend = function() {
$.ajax({
type: 'POST',
url: GOOGLE_CLOUD_FUNCTION_URL,
data: this.result,
dataType: 'json',
processData: false,
contentType: 'application/octet-stream',
success: function(resp) {
},
error: function(err) {
}
});
};
fileReader.readAsArrayBuffer(blob);
and my Google Cloud Functions module looks like this:
exports.upload = function(req, resp) {
resp.header('Content-Type','application/json');
resp.header('Access-Control-Allow-Origin', req.get('origin'));
resp.header('Access-Control-Allow-Headers', 'Content-Type');
switch (req.method) {
case 'POST':
response.status(200).send({
contentType: request.get('content-type'),
body: request.body,
rawBody: request.rawBody
});
break;
}
};
The request header shows that that there is data being attached. But, the content-type is not set as `application/octet-stream'. In addition the response returns:
{
body: {}
}
What is the JavaScript type of data to pass to an ajax body for the Google Cloud Functions HTTP handler accept the body as a Buffer?
Blob, File, Typed Array, Array Buffer?

File upload to the asp.net web service not working

I'm trying to upload file to the web service using JavaScript and JQuery. My current implementation is working correctly in the local environment.
But after deploying my solution to the server and try to access from outside it's not working and saying server side error occurred. Other thing I found is other web methods of the same web service are working correctly and just this file upload method is not working.
Here is my asp.net web service file upload method.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public object SaveFile()
{
var bugID = int.Parse(HttpContext.Current.Request.Form["bugID"]);
var fileName = HttpContext.Current.Request.Form["name"];
var fileType = HttpContext.Current.Request.Form["type"];
var file = HttpContext.Current.Request.Files[0];
// file saving logic
// .....
return new JavaScriptSerializer().Serialize(new
{
Message = 1,
Name = fileName,
DocumentID = attach.DocumentID // Saved file ID
});
}
Here is the javascript method I used to upload the file to the web service
function uploadFile() {
var data = new FormData(),
file = $("#fileToUpload")[0].files[0];
data.append("name", file.name);
data.append("size", file.size);
data.append("type", file.type);
data.append("file", file);
data.append("bugID", bugID);
$.ajax(
{
url: baseURL + "Webservice/BugsWebService.asmx/SaveFile",
dataType: "xml",
type: "POST",
data: data,
cache: false,
contentType: false,
processData: false,
success: function (res) {
console.log(res);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
console.log(textStatus);
console.log(errorThrown);
}
});
}
In development environment web service url is
http://localhost:55225/Bugs/View.aspx
When host the site url is
http://[ip-address]/Internal/Bugs/View.aspx
This is the error I'm getting when try to upload the file
http://[ip-address]/Internal/Webservice/BugsWebService.asmx/SaveFile
500 (Internal Server Error)
What is the issue with my implementation?

Upload files to Dropbox using a Dropbox Core API in Javascript

I am working on a simple chrome-extension that needs to upload files to the user's dropbox folder. I am using the simple AJAX requests as mentioned below to upload files, however it works for files with extensions such as .txt, .json, .c, etc i.e. files whose mime type is of type text/plain or similar type but all other file types such as pdfs, image files etc get corrupted and produce blank contents. What am I missing in uploading the files the correct way.
function startUpload()
{
var folderPath = $(this).closest('tr').attr('path')+'/';
var file = $("#upload_file")[0].files[0];
if (!file){
alert ("No file selected to upload.");
return false;
}
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
uploadFile(folderPath+file.name,evt.target.result,file.size,file.type);
}
}
//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)
{
getMetadata(filepath.substring(0,filepath.lastIndexOf('/')),createFolderViews);
},
error: function(jqXHR)
{
console.log(jqXHR);
}
};
$.ajax(args);
}
I believe the issue is reader.readAsTextFile(file, "UTF-8"). If the file isn't a text file, this will misinterpret the contents. I think you want reader.readAsBinaryString or reader.readAsArrayBuffer. (I haven't tested it myself.)
EDIT
After testing this myself, I found that readAsArrayBuffer is what you need, but you also need to add processData: false as an option to $.ajax to prevent jQuery from trying to convert the data to fields in a form submission.
Also be sure to use dataType: 'json' to properly parse the response from the server.

Categories

Resources