Javascript + Multipart/Form Data - javascript

I have a service which allows to fill information about some object. One of the attributes is picture. Before now I used to upload picture through file open dialog from desktop. Now want to make it possible to load picture by URL, but I have no idea how to load it by URL and make it a form-data parameter (so that both ways were possible). I'm constructing form-data like this
var fd = new FormData();
fd.append("img", imgFile);
fd.append("data", "somedata")

Try this implementation. Uploading files and JSON data in the same request with Angular JS

Related

how to generate a url for a file without URL.createobjectURL() javascript

I would like to create a url for any file that is passed in so that on click of the url, the file can be viewed. However, using URl.createobjectURL results in a blob url. I would like to avoid this. Are there any other alternatives for creating file urls?

How can we know the content of a file from a Javascript File object?

One common way to make asynchronous file upload that I could find on the web works as follow :
myUpload(ev) {
ev.preventDefault();
const data = new FormData();
data.append('file', this.uploadInput.files[0]);
/* Do the upload with something like axios */
axios.post('http://localhost:8000/upload', data)
. ...
}
I cannot explain the following :
the object this.uploadInput.files[0] is a File javascript object.
From the documentation I could find (see for instance this), and from the log I tried on the console, javascript File objects store neither the file content, nor the file path.
Therefore, how can the FormData object retrieve the file data we want to send ?
FormData probably doesn't, but the browser does because when axios provides the FormData object to the browser's ajax features (XHR or fetch), the browser can use the data in¹ the File object to read and send the file.
Your own JavaScript code could also use the data in the File object to read the file, using FileReader (another browser-supplied feature).
File doesn't directly contain the file's data, but it does contain information the browser can use to read the file (without exposing its actual location to your code).
¹ Probably not literally in the File object. More likely an indirect relationship between the two using data privately-held by the browser.

Adding metadata or tags on S3 Upload with FormData

I'm uploading a file to S3 and I'd like to attach some metadata/tags to it, but unfortunately I'm unable to do so it seems with my current method.
I'm creating a FormData object in Javascript and appending a couple of tags that I read through the S3 documentation are required in order to attach metadata with the file.
Here is the file info (which gets uploading fine, already):
fd.append('AWSAccessKeyId', presignedRes.data.fields.AWSAccessKeyId);
fd.append('key', presignedRes.data.fields.key);
fd.append('policy', presignedRes.data.fields.policy);
fd.append('signature', presignedRes.data.fields.signature);
fd.append('acl', 'bucket-owner-full-control');
fd.append('file', parsedFile);
And below is the metadata I'm attempting to attach. I'd like to have it be JSON if possible.
fd.append('x-amz-meta-tag', JSON.stringify([{'name': 'email'}]));
Unfortunately when the upload submits to S3 successfully, it fails to pass through this metadata above.
I'd like to do this if possible without having to use the aws node library.

Upload images to S3 doesn't work

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.

Post file from one remote server to another

I'm writing a Google Chrome extension. I have URL of a binary file on a remote server. I want to post that file to other server. So related function should look like this.
function postFileToExampleCom(fileUrl) {
var file = ???; // Blob with data from file located at fileUrl
var form = new FormData();
form.append('file', file);
var request = new XMLHttpRequest();
request.open('POST', 'http://example.com/post/', true);
request.send(form);
}
FormData.append() expects second argument to be a Blob object containing file data. What is the best way to get it? File is likely to be an image that is already loaded in active tab so it's preferable to use cache and not to download this file again.
UPD: I've tried downloading file with another XMLHttpRequest setting responseType = 'blob' but strangely it returns empty response.
".. File is likely to be an image that is already loaded in active tab so it's preferable to use cache and not to download this file again."
If you saved the file locally (e.g. using localStorage or fileAPI) - then you should make sure you reading it and getting a file back and not a serialized version of the data.
I would debug the line of 'var file=???' and see what is the obj that you getting there.
It's good practice to have these 3 functions for your 'request':
onload, onerror and onprogress.
I hope it helps.

Categories