I'm trying to upload an image file from an html page to azure blob storage. So far I have written a web service to create an SAS for my blob container. From this I have created a uri of the format "blob address" / "container name" / "blob name" ? "sas". I have an upload control on my html page.
I have then tried to upload the file using the following code:
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.addEventListener("error", uploadFailed, false);
xhr.addEventListener("abort", uploadCanceled, false);
xhr.open("PUT", blobPath);
xhr.send(upFile.files[0]);
where blobPath is the uri as above and upFile is my html upload control.
When I try to upload a file the uploadFailed routine is triggered. So:
Is this the right way to do this?
How do I trap the error returned by the upload so that I can see what is going wrong?
My sas looks like: "sr=c&si=mypolicy&sig=onZTE4buyh3JEQT3%2B4cJ6uwnWX7LUh7fYQH2wKsRuCg%3D"
Any help appreciated, thanks.
This is certainly the right way however there're a few things:
You have to include x-ms-blob-type request header in your request and it's value should be BlockBlob.
Also please realize that for this to work, you would need to host your HTML page in the same storage account because CORS is not supported in Azure Blob Storage as of today. So if your html page is hosted in some other domain, you would get error because of CORS.
You may find these blog posts useful for uploading blobs using SAS and AJAX:
http://coderead.wordpress.com/2012/11/21/uploading-files-directly-to-blob-storage-from-the-browser/
http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/
I have now found a solution that works for this problem. My upload now works as follows:
I read the file as a DataURL into a FileReader
I slice the returned string up and send each slice up to the server
where it is stored in a session variable
Once the whole file has been sent up I call another web service which
glues the slices back together and turns the result into a byte array
The byte array is then stored as a file in local storage in azure
Finally the file is transferred from local storage into blob storage
See code at:
Upload files from html to azure
Related
I'm developing a Chrome extension in which I generate a CSV file and when a button is clicked, I want to store this CSV file in the user's drive.
I first tried to add the "Save to Drive" button/widget (https://developers.google.com/drive/api/v3/savetodrive) in my HTML, however I found out this won't work as my CSV file is not stored locally but generated from text content, using: blob = new Blob([csv], {type: "text/csv"}); href = window.URL.createObjectURL(blob);, where csv is a string storing the CSV formatted data. As a result of this the href variable is not a URL, but a blob URI which isn't supported as a data-src attribute when using the Save to Drive button (From the docs: "Data URIs and file:// URLs are not supported")
The second approach is to use the Google Drive API, however I haven't found any good examples on how to use this API on just purely front-end applications with no backend. Most of the documentation's example are all in Python or node. The only browser based example in the docs (https://developers.google.com/drive/api/v3/quickstart/js) requires a localhost server to run which won't be possible in a Chrome extension. Trying this example found in the docs without running a localhost server, results in the following error: Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('file://') does not match the recipient window's origin ('null').
I know that the Drive API's upload endpoint supports CORS, so I don't know why I would need a localhost server to make requests to the Drive API or to use the gapi.client from https://apis.google.com/js/api.js. In summary, I don't believe what I'm looking for is too complicated; save a CSV file to someones Google Drive without using a backend server. It seems like its possible but I haven't come across any examples or documentation on how to achieve this on purely front-end applications.
function saveToDrive() { // Function that is called when the button is clicked.
csv = document.getElementById("userInput").value // User inputs CSV formatted data, this data is captured and stored in a string
blob = new Blob([csv], {type: "text/csv"});
href = window.URL.createObjectURL(blob);
// Code to upload this file to the logged in user's Google Drive (what I need)
}
I want to upload two files to a web service, one CSV file with metadata inside and one tiff image. The CSV file and the tiff files are are a pair, because the CSV file contains metadata for the tiff file. So they always need to be uploaded together
I have the javascript working on an uploading server
var xhr = new XMLHttpRequest();
var formData = new FormData();
xhr.open('POST', '/GigaTEMUpload/UploadFiles', true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
files.forEach(function (file, i) {
formData.append('uploadFiles[' + i + ']', file);
});
xhr.send(formData);
but if I want to use python request to do the same post job how to do it through python?
Thanks
I am using python from a server running spyder to upload two files to a web. And once they are uploaded the tiff image would be viewable on the web.
It's a pretty normal outbound request. Here is a similar question for your reference,
Send file using POST from a Python script
I am currently using RecorderJS and need to send a .wav file to the backend. the API is quite limited in documentation so I am struggling to figure out how to send the .wav file through my axios.post(...).
I am able to download the .wav file with
Recorder.download(theblob, 'audio.wav');
this downloads a .wav file which I can play through itunes so it is the right format. I now need to figure out how to save this in a variable in order to post it through axios. Also, what should i use for me headers, .. ect?
Looking for any kind of javascript solution to this. I just need to send the exact downloaded file to my backend. Thanks!
The download method stores the file somewhere on your disk. I believe javascript cannot traverse your computer's path and read files for security reasons. I'm not sure if recorder-js offers storing it in a variable "out of the box", so you may want to get that handled first.
For your second part of the question:
This should work for posting it to the back-end:
let data = new FormData();
data.append('wavfile', file, file.name);
const config = {
headers: { 'content-type': 'multipart/form-data' }
}
axios.post('/api/recorderfiles', data, config)
I'm trying to upload files to S3 without having to send to my server. I've a endpoint which gives me signed S3 URL where I can make PUT requests to store files to my bucket.
I tried to do couple of things on JavaScript side which didn't work. (I'm not using amazon's SDK, and prefer not to, because I'm looking for simple file upload and nothing more than that)
Here's what I'm trying to do currently in JavaScript:
uploadToS3 = () => {
let file = this.state.files[0];
let formData = new FormData();
formData.append('Content-Type', file.type);
formData.append('file', file);
let xhr = new XMLHttpRequest();
xhr.open('put', this.signed_url, true);
xhr.send(formData)
};
I tried bunch of options, I prefer using fetch because I don't really care for upload progress since these are just images. I used xhr code from somewhere to try out like above. These do make network calls and seem like they should work but they don't.
Here's what happens: An object is created on S3, when I go to public URL, they get downloaded and when I use image viewer to open them, they say it's not valid JPG.
I'm thinking I'm not doing the upload correctly.
Here's how I do in postman:
Notice I have correct signed URL and I've attached binary image file to the request. And added a header stating content type is image/jpeg as shown below:
When I login to S3 and go to my bucket, I can see an image and I can go to it's public URL and view in browser. This works perfect and is exactly what I want, now I don't know how I could achieve the same on JavaScript.
PS: I even tried to click on code on postman, it doesn't generate file code for me.
The problem here starts with xhr.send(formData).
When you PUT a file in S3 you don't use any form structures at all, you just send the raw object bytes in the request body.
Content-Type: and other metadata goes in the request headers, not in form data in the body.
In this case, if you download your uploaded file and view it with a text editor, the problem should be very apparent once you see what your code is actually sending to S3, which S3 then obediently stores and serves up on subsequent requests.
Note that S3 does have support for browser-based form POST uploads, but when doing so the signing process is significantly different, requiring you to create and sign a policy document, so that you can send the form, including the policy and signature, to the browser and allow an otherwise-untrusted user to upload a file -- the signed policy statement prevents the browser user from tampering with the form and performing actions that you didn't intend.
A file sharing website known as mega.com has a feature that creates a custom download manager. When you download a file, it shows a custom progress bar on the website (presumably loading the file to the cache), then creates a download prompt for the cached file. How would this be produced with javascript?
As far as I know, Mega.com uses this inner download manager because they store data on their servers in an encrypted form; encryption and decryption take place in the browser.
Storage
You can use IndexedDB to store binary data. Here's a tutorial from Mozilla, explaining how to download an image using AJAX and save it in IndexedDB.
When you have data stored in IndexedDB you should have opportunity to download it (from internal browser storage). Here you can read, how to create a download prompt.
Progress bar
When using XMLHttpRequest, you can get download progress by providing a handler for the progress event.
var oReq = new XMLHttpRequest();
oReq.addEventListener("progress", updateProgress, false);
[...]
function updateProgress (oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = oEvent.loaded / oEvent.total;
// ...
} else {
// Unable to compute progress information since the total size is unknown
}
}
Total size of the file would be unavailable if server didn't send Content-Length with headers.
Full source code and description on MDN.
There is a complete answer for your question: http://tonistiigi.github.io/mega/.
If you want to create a download manager in JavaScript, these articles will help you do your work:
http://www.andymatthews.net/read/2010/09/28/File-downloading-with-Adobe-AIR-using-HTML-and-jQuery
http://www.andymatthews.net/read/2010/10/21/Downloading-Files-with-Adobe-AIR,-HTML-and-JS-Part-2.-Adding-a-Progress-Bar-with-Canvas
If you want to create a file download progress, please go to this link: Javascript source file download progress?.
Please put more thought, time, and effort into your to make your work done. If you can't, please post a comment bellow my own answer; I will help you to do it detailly.