没有. html 扩展名的 S3静态页面

在服务 Amazon S3之外的静态站点时,我想知道如何去掉每个页面的 .html文件扩展名。

现在我有:

mysite.com/             # works fine, serves index.html
mysite.com/mypage.html  # works fine
mysite.com/mypage       # doesn't work

/mypage的错误显示:

404 Not Found


Code: NoSuchKey
Message: The specified key does not exist.
Key: mypage
RequestId: 1089D7A26EFED9AD
HostId: Ud8cFy8Zl1mJ+oFjFOmU1Xacq9+v70KuaJfOc4nFMEPhd66AkLhr4Pj5u0QH6Gog

我已经尝试设置的 Content-Typetext/html,根据 这篇文章,但它不能解决我的问题。

如何让 /mypage在 S3上的 /mypage.html服务该文件?

39926 次浏览

In general on Amazon S3, to create clean URLs you can:

  1. Upload the page file with a "clean" name, e.g. mypage and set the Content-Type set to text/html (as the post you linked to described). You must rename the file on your system before you upload it to have no extension, or rename it without the extension on S3 after uploading. The file's name on S3 must not have an extension.

  2. Create a folder with the "clean" name and upload the page file to that folder with its name set to the default index document, e.g. index.html. You need to check what the default index document name is. This is set when you configure your bucket as a website, but can be changed later.

If you can't make the above work you can upload a new zero-byte object with the name key mypage and then set a page redirect by specifying the Website Redirect Location key with a value mypage.html in the metadata during the upload process. See Configuring a Web Page Redirect in the Amazon S3 documentation.

You could also copy the file to a new object named mypage with Content-Type set to text/html.

Creating a folder at /mypage and putting index.html inside of it wasn't working for me. It turns out that this was because the Bucket's "Index Document" setting had been changed to myindex.html:

Bucket Properties --> Static Website Hosting --> Enable Website Hosting --> Index Document

This was actually being applied to all subfolders too, so that it wasn't looking for /mypage/index.html when on the /mypage route; it was looking for /mypage/myindex.html instead.

I simply changed the myindex.html setting back to index.html, and the standard folder structure works. It would have worked equally as well to use myindex.html files everywhere with that setting in place, but that seemed confusing for no real gain.

I still don't know why setting the Content-Type to text/html doesn't work -- seems like it should as that is mentioned in several places.

Anyway, the problem is solved by changing the Bucket's Index Document and all subfolders to use index.html.

I just had this problem and I'd like to share the solution:

You have to set the meta data of the file Content-type to text/html AND rename the file removing the .html of the end.

That way you will be able to reach every page without the file extension.

Very Simple and Tested Solution. :

  1. Rename file, Remove Extension (.html) from file name. (ex. change gallery.html to gallery).
  2. Edit Properties of File. Add Metadata key (Content type = text/html and content language = html).
  3. Save and test from browser url like websiteurl.com/gallery.

As some have said already, delete the file extension, but then simply follow the following steps:

  1. Go to your Amazon S3 bucket.
  2. Select the checkbox next to the file you'd like to have linking properly.
  3. Click "Properties" on the right, and a new pane will show up. It'll say "Object: filename"
  4. Click the Metadata tab, change from default, which for me was "binary/octet-stream"; new value should be "text/html".
  5. Save.

And as people have said, make sure your new links in your html don't contain the .html file extension anymore. This worked for me.

With the AWS CLI:

Assuming that you have removed the extension from the filename and set up AWS CLI with your account, you can set the meta data of the file by running this command in your console:

aws s3 cp /path/to/file s3://yourwebsite.com --content-type 'text/html' --acl public-read

Another possible solution is to use Lambda@edge power, documentation reference here.

If you want to upload json file. Save the json file without extension in your local machine.

From AWS CLI use below command :

  aws s3 mb s3://<s3bucketname>


#output
make_bucket: s3bucketname


aws s3 cp path\to\local\file s3://<s3bucketname>  --content-type 'application/json' --acl public-read


#output
upload: .\<filename> to s3://<s3bucketname>/<filename>

now you can access the file using url:

https://<s3bucketname>.s3.amazonaws.com/<filename>

I added some automated script example to remove *.HTML extension and uploaded to s3 by added content-type of meta-object. I use javascript to create sh file, I run sh file.

const recursive = require("recursive-readdir");
const fs = require("fs");


(async (params) => {
let buffer = "aws s3 cp ./out s3://www.Example.com \n";
await recursive("out", [
"css",
"_next",
"images",
"static",
"svg",
"*.ico",
"*.txt",
"*.xml",
"index.html",
"404.html",
]).then(
(files) => {
     

    

for (const file of files) {
const path = file.substring(file.indexOf("\\") + 1);


buffer += `aws s3 cp --content-type 'text/html' --metadata-directive REPLACE ./out/${path}  s3://www.example.com/${path} \n`;


const removeExtension = file.replace(/\.[^/.]+$/, "");


fs.rename(file, removeExtension, function (err) {
if (err) console.log("ERROR: " + err);
});
}
   

},
(error) => {
console.error("something exploded", error);
}
);


  





fs.writeFileSync("deploy.sh", "echo 'copy your files' \n");
fs.appendFileSync("deploy.sh", buffer);


fs.appendFileSync("deploy.sh", 'echo "Invalidation cloudfront"');
fs.appendFileSync("deploy.sh", 'aws cloudfront create-invalidation --distribution-id XXXXXXX --paths "/*" ');










})();


The reason it works without the trailing slash on the root domain is because you have this structure for your main index:

mysite.com/index.html

Then the server goes and servers the index default page, showing:

mysite.com/

If you don't want the traling slash for all your pages you should do the same for all your html files. Instead of

mysite.com/mypage.html

Do

mysite.com/mypage/index.html

Then the server will show the default index file for the mypage folder, showing in the url

mysite.com/mypage/

In a multipage web app (say 12 pages), the accepted answer will be inefficient since manually editing the file extension and format is required on every upload.

An automated and worry-less strategy is to use AWS Lamda@Edge. It solves this completely.

First, create an AWS Lambda function and then attach your CloudFront as a trigger.

In the code section of this AWS Lamda page, add the snippet in the repository below.

https://github.com/CloudUnder/lambda-edge-nice-urls/blob/master/lambdaRewrite.js

Content delivery will still be as fast as you can blink your eyes.

PS: Note the options in the readme section of the repo above

I was able to get a Cloudfront function to work. Its much cheaper then the lambda solution provided and you don't need to serve html files with no extension. This is a very slight change to a chunk of code to get subdirectories working in CF.

'use-strict';
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
else if (!uri.includes('.')) {
request.uri += '.html';
}
return request;
}

Caveat, I don't have a remove trailing slash solution figured out just yet but this chunk of code will fix your problem.