Display image from s3 - html

I am trying to display images that I have uploaded to S3. I believe the permissions are correct as I can hit the url and get data back. However when I put the URL in an image tag I get a broken link.
When I put the image tag on my site in the network tab I see the call to s3 (with a 200 response) but an empty body. If I hit the s3 url directly I get the data back and in the network tab I see the call WITH a response body from s3.
I'm uploading the images from a Vue frontend to an express/node backend. I see the images fine in s3.
s3.putObject({
Bucket: 'MYBUCKET',
Key: `${result._id}-${file.upload.filename}`,
Body: file.dataURL,
ACL: 'public-read',
ContentType: 'binary',
ContentEncoding: 'utf8'
}, function (resp) {});
Fiddle: https://jsfiddle.net/Xadvz/7327/
I use the data I get back from hitting s3 directly and it displays the image but when I put in the s3 url it displays a broken link.

S3 does not support dataURL data format.
In your backend:
convert dataURL to buffer
set ContentType of S3 object according to dataURL
code:
var regex = /^data:.+\/(.+);base64,(.*)$/;
var matches = file.dataURL.match(regex);
var ext = matches[1]; // image/jpeg
var data = matches[2]; // base64 string
var buffer = new Buffer(data, 'base64');
s3.putObject({
Bucket: 'MYBUCKET',
Key: `${result._id}-${file.upload.filename}`,
Body: buffer, // upload binary
ACL: 'public-read',
ContentType: ext // set content type
}, function (resp) {});

Are you sure Content-Type: 'binary' is correct? The value is identical to MIME type. Here's some typical types:
*.jpg .................................. image/jpeg
*.html ................................. text/html
*.txt ..................................... text/plain
*.mp3 .................................. audio/mpeg
Unknown/Default .............. application/octet-stream
Content-Type values must conform to the same syntax as MIME type:
type/sub-type
If you aren't sure you should at least use application/octet-stream

Related

Upload JSON data with Google Drive API in the browser

The Google Drive API lets us upload JSON files like that:
const fileMetadata = {
name: "config.json",
};
const media = {
mimeType: "application/json",
body: fs.createReadStream("files/config.json"),
};
const file = await gapi.client.files.create({
resource: fileMetadata,
media: media,
fields: "id",
});
console.log("File Id:", file.data.id);
This works fine in Node.js, but i want this to run in the browser, however, when i pass the media argument, with the body set to a string, an empty Untitled file is created without any extension.
The filename only works when media is not present.
My question is: How to pass data for a JSON from a string, so it can be read later?
I already tried creating the file and updating it later with its ID.

AWS S3 - Allow public to view HTML files

I am looking to allow public users to view HTML files located on an AWS S3 bucket on their browser. These HTML files are created and uploaded to my S3 bucket via node.js, and a URL linking to the file is generated.
I am using this method to upload the HTML files:
s3.upload({
Bucket: bucket,
Key: "HTMLFiles/file.HTML",
Body: fileStream,
ACL: 'public-read'
}, function (err, data) {
if (err) {
console.log("Error: ", err);
}
if (data) {
console.log("Success: ", data.Location);
}
}).on('httpUploadProgress', event => {
console.log(`Uploaded ${event.loaded} out of ${event.total}`);
});
When the script is run, the generated URL looks something like this:
https://bucket-name.s3.region.amazonaws.com/HTMLFiles/file.html
(Obviously this is only an example URL and not the actual URL)
When a user goes to this URL, instead of viewing the HTML file, the browser instead downloads the file.
How can I specify that this file is meant to be loaded on the browser and viewed, not downloaded?
This is because the content type is missing so the browser doesn't know that your file should be interpreted as HTML.
Please add ContentType: 'text/html' in the parameters passed to s3.upload.
See also the explanations and links given in Upload Image into S3 bucket using Api Gateway, Lambda funnction

Sending image in correct format to Google Cloud Storage

I'm currently using the JSON API to send an image to GCS. However, when I send an image in base64, the image does not show up. Here is my request code
fetch(gcloud_storage_url+`?uploadType=media&name=${name}`, {
method: 'post',
headers: {
'Content-Type': 'image/jpeg',
'Authorization': 'Bearer ' + token,
},
body: JSON.stringify({image: imageBase64})
}).then(resp => { console.log(resp) })
Not sure if my post body is in the wrong format.
As per the documentation, when using JSON API to upload image to Cloud Storage where ‘uploadType=media’, make sure the media is less than 5 MB and it does not contain metadata. If you have bigger media file or metadata, use ‘multipart’ or ‘resumable’ for ‘uploadType’. Here is an example of the upload method. If not, as Oliver commented, please provide any error or response information.

AJAX works when extension is .json but not when it is .html

So I have an ajax request. When I use .html as below. I receive:
Failed to load resource: the server responded with a status of 406 (Not Acceptable)
When i use .json I receive the correct output. Why does it not work with .html
$("input[value = 'Add Type Targets']")
.click(
function() {
var promise = $
.ajax({
url : '/MyRoot/budget/myUrl.html',
type : 'GET',
beforeSend : function(
xhr) {
xhr
.setRequestHeader(
"Accept",
"application/json");
xhr
.setRequestHeader(
"Content-Type",
"application/json");
}
});
promise
.done(function(data) {
someCode
}
});
});
On the method I have
#RequestMapping(value = "/myUrl", method = RequestMethod.GET, produces = "application/json")
public #ResponseBody List<String> getData() {
return staticDataService.getData();
}
I have the jackson-mapper-asl-1.9.10.jar and jackson-core-asl-1.9.10.jar added.
Is it that because of the .html extension my response header is getting altered. Actually it is not even hitting my method when i use .html.
The HTTP error code 406 (Not Acceptable) means your HTTP request specified that the result must be of a certain type.
In your code, you explicitly mention that you only accept JSON results.
$.ajax({
url : '/MyRoot/budget/myUrl.html',
type : 'GET',
beforeSend : function(xhr) {
xhr.setRequestHeader( "Accept", "application/json");
...
When the server sees a file with a .json extension, it will automatically give it an application/json content-type, while a .html file, with be text/html content-type.
Since these are very different, you see the 406 error.
Since you are actually returning JSON, I would suggest you also use that for the extension. Not only will this help prevent confusion for other developers, it will also prevent you from having to 'fight the system'.
If you for some reason do want the HTML extension, you could try forcing the response content-type to be application/json. Since this extension based content-type is typically added by the server (IIS, Apache, etc.), it depends on your development stack if you can override this.
In ASP.NET you would use the following to explicitly set a header, but I can't say for sure if this will override the settings in IIS.
Response.ContentType = "application/json"
Should this not work, you can also change your AJAX call to be more permissive with it's response accepting.
xhr.setRequestHeader( "Accept", "*/*");

Angular gzip json file automatically : Refused to set unsafe header "Accept-Encoding"

I use a gzip json static file on my server (actually, it's my test server) and the data i receive is always compressed.
Here is my code :
$http({
url :'app/assets/json/makes2v.json.gz',
method: "GET",
headers: { 'Accept-Encoding': 'gzip' }})
.success(function(data, status, headers, config) {
console.log(data);
});
I use angular 1.3.15 and Chrome.
In the console I have this error:
Refused to set unsafe header "Accept-Encoding"
Any help will be appreciated.
Thanks,
You shouldn't set the request header "Accept-Encoding". This is set automatically by the browser. See this Q&A for a list a browsers that accept gzip.
On the server side, you will need to set the Content-Encoding to:
Content-Encoding: gzip
Then the response should be automatically decompressed by the browser.