mirror of
https://github.com/MarSeventh/CloudFlare-ImgBed.git
synced 2026-04-25 06:35:21 +00:00
支持自定义压缩
支持链接自动复制到剪切板 支持多种设置记忆 增加仅删除上传成功图片,上传失败图片重试 优化粘贴上传时的文件命名 优化多处细节,提升使用体验
This commit is contained in:
27
README.md
27
README.md
@@ -1,6 +1,6 @@
|
||||
# CloudFlare-ImgBed
|
||||
|
||||
免费图片托管解决方案,基于 Cloudflare Pages 和 Telegram (文件大小不建议超过20MB,过大图片会**自动压缩**)。
|
||||
免费图片托管解决方案,基于 Cloudflare Pages 和 Telegram (文件大小不超过50MB,过大图片会**自动压缩**)。
|
||||
|
||||
**体验地址**:[Sanyue ImgHub (demo-cloudflare-imgbed.pages.dev)](https://demo-cloudflare-imgbed.pages.dev/)
|
||||
|
||||
@@ -33,15 +33,13 @@
|
||||
|
||||
免费图片托管解决方案(支持存储绝大多数常见格式的**图片、视频、动图**等),具有**后台管理、图片审查**、**登录鉴权**、**页面自定义**、**多种方式及多文件上传**、**多文件及多格式链接复制**等功能(详见[第2章](#2.Features))。
|
||||
|
||||
此外,拖拽上传的方式**并没有严格限制文件类型**,理论上你可以上传**任何**不超过20MB的文件,但是暂时不会针对图片和视频外的文件进行特殊优化和适配。
|
||||
此外,拖拽上传的方式**并没有严格限制文件类型**,理论上你可以上传**任何**不超过50MB的文件,但是暂时不会针对图片和视频外的文件进行特殊优化和适配。
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
@@ -57,12 +55,13 @@
|
||||
- **人性化上传**
|
||||
|
||||
- 支持绝大多数常见**图片、视频、动图**等
|
||||
- 支持一键切换上传方式(**拖拽点击、粘贴**)
|
||||
- 支持多种上传方式(**拖拽点击、粘贴**)
|
||||
- 粘贴上传支持**文件**和**URL**
|
||||
- 支持批量上传(不限同时选择文件数量,但为了保证稳定性,同时处于上传状态的文件最多为10个)
|
||||
- 上传显示实时上传进度
|
||||
- **上传后图片无需手动点击,可直接展示在管理页面中**
|
||||
- **过大图片在前端进行压缩,提升上传稳定性和加载性能**
|
||||
- 支持自定义压缩质量,自定义开启前后端压缩功能
|
||||
|
||||
- **多样化复制**
|
||||
|
||||
@@ -227,7 +226,7 @@ API格式:
|
||||
| ------------ | ------------------------------------------------------------ |
|
||||
| **接口功能** | 上传图片或视频 |
|
||||
| **请求方法** | POST |
|
||||
| **请求参数** | **Query参数**:<br />`authCode`,string类型,即为你设置的认证码<br />**Body参数(application/form-data)**:<br />`file`,file类型,你要上传的文件 |
|
||||
| **请求参数** | **Query参数**:<br />`authCode`,string类型,即为你设置的认证码<br />`serverCompress`,boolean类型,表示是否开启服务端压缩(仅针对图片文件生效)<br />**Body参数(application/form-data)**:<br />`file`,file类型,你要上传的文件 |
|
||||
| **返回响应** | `data[0].src`为获得的图片链接(注意不包含域名,需要自己添加) |
|
||||
|
||||
> **请求示例**:
|
||||
@@ -359,13 +358,13 @@ API格式:
|
||||
7. ~~完善登录逻辑,后端增加认证码校验接口(2024.8.21已完成)~~
|
||||
8. ~~支持URL粘贴上传(2024.8.23已完成)~~
|
||||
9. ~~支持大于5MB的图片上传前自动压缩(2024.8.26已完成)~~
|
||||
10. 上传页面右下角工具栏样式重构,支持上传页自定义压缩(上传前+存储端)
|
||||
10. ~~上传页面右下角工具栏样式重构,支持上传页自定义压缩(上传前+存储端)~~(2024.9.28已完成)
|
||||
11. 重构管理端,认证+显示效果优化,增加图片详情页
|
||||
12. 管理端增加访问量统计,IP记录、IP黑名单等
|
||||
13. 上传页面点击链接,自动复制到剪切板
|
||||
14. 上传设置记忆(上传方式、链接格式等)
|
||||
15. 若未设置密码,无需跳转进入登录页
|
||||
16. 增加仅删除上传成功图片、上传失败图片重试
|
||||
13. ~~上传页面点击链接,自动复制到剪切板~~(2024.9.27已完成)
|
||||
14. ~~上传设置记忆(上传方式、链接格式等)~~(2024.9.27已完成,**两种上传方式合并**)
|
||||
15. ~~若未设置密码,无需跳转进入登录页~~(2024.9.27已完成)
|
||||
16. ~~增加仅删除上传成功图片、上传失败图片重试~~(2024.9.28已完成)
|
||||
17. ~~优化粘贴上传时文件命名方法(2024.9.26已完成)~~
|
||||
|
||||
### 4.2Fix Bugs👻
|
||||
|
||||
1
css/538.af586728.css
Normal file
1
css/538.af586728.css
Normal file
File diff suppressed because one or more lines are too long
BIN
css/538.af586728.css.gz
Normal file
BIN
css/538.af586728.css.gz
Normal file
Binary file not shown.
1
css/782.8fd7696b.css
Normal file
1
css/782.8fd7696b.css
Normal file
@@ -0,0 +1 @@
|
||||
.login[data-v-50aaab2d]{display:flex;justify-content:center;align-items:center;height:100vh;background:linear-gradient(90deg,#ffd7e4,#c8f1ff)}.login-container[data-v-50aaab2d]{display:flex;flex-direction:column;justify-content:space-around;align-items:center;height:40vh;width:40vw;border-radius:12px;box-shadow:0 0 12px rgba(0,0,0,.12);background-color:hsla(0,0%,100%,.6);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:all .3s ease}@media (max-width:768px){.login-container[data-v-50aaab2d]{width:80vw}}.login-container[data-v-50aaab2d]:hover{box-shadow:0 0 12px 4px rgba(0,0,0,.24);transform:translateY(-5px)}.input-container[data-v-50aaab2d]{display:flex;align-items:center;width:35vw}@media (max-width:768px){.input-container[data-v-50aaab2d]{width:75vw}}.input-name[data-v-50aaab2d]{width:12vw}@media (max-width:768px){.input-name[data-v-50aaab2d]{width:28vw}}.submit[data-v-50aaab2d]{margin-top:10px}.password-input[data-v-50aaab2d]{height:40px}.password-input[data-v-50aaab2d] .el-input__wrapper{border-radius:12px;background-color:hsla(0,0%,100%,.9);box-shadow:none}.username-input[data-v-50aaab2d]{height:40px}.username-input[data-v-50aaab2d] .el-input__wrapper{border-radius:12px;background-color:hsla(0,0%,100%,.9);box-shadow:none}
|
||||
BIN
css/782.8fd7696b.css.gz
Normal file
BIN
css/782.8fd7696b.css.gz
Normal file
Binary file not shown.
1
css/880.f72995a0.css
Normal file
1
css/880.f72995a0.css
Normal file
File diff suppressed because one or more lines are too long
BIN
css/880.f72995a0.css.gz
Normal file
BIN
css/880.f72995a0.css.gz
Normal file
Binary file not shown.
1
css/986.0b7ed77b.css
Normal file
1
css/986.0b7ed77b.css
Normal file
@@ -0,0 +1 @@
|
||||
.login[data-v-1774635e]{display:flex;justify-content:center;align-items:center;height:100vh;transition:background-image 1s ease-in-out;background-size:cover;background-attachment:fixed}.login-container[data-v-1774635e]{display:flex;flex-direction:column;justify-content:space-around;align-items:center;height:40vh;width:40vw;border-radius:12px;box-shadow:0 0 12px rgba(0,0,0,.12);background-color:hsla(0,0%,100%,.6);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);transition:all .3s ease}@media (max-width:768px){.login-container[data-v-1774635e]{width:80vw}}.login-container[data-v-1774635e]:hover{box-shadow:0 0 12px 4px rgba(0,0,0,.24);transform:translateY(-5px)}.password-input[data-v-1774635e]{margin-bottom:15px;width:30vw;height:40px}.password-input[data-v-1774635e] .el-input__wrapper{border-radius:12px;background-color:hsla(0,0%,100%,.7);box-shadow:none}@media (max-width:768px){.password-input[data-v-1774635e]{width:70vw}}.submit[data-v-1774635e]{margin-top:10px}.background-image1[data-v-1774635e],.background-image2[data-v-1774635e]{position:fixed;top:0;left:0;width:100%;height:100%;-o-object-fit:cover;object-fit:cover;z-index:-1;opacity:0;transition:all 1s ease-in-out}
|
||||
BIN
css/986.0b7ed77b.css.gz
Normal file
BIN
css/986.0b7ed77b.css.gz
Normal file
Binary file not shown.
@@ -83,7 +83,7 @@ export async function onRequest(context) { // Contents of context object
|
||||
|
||||
try {
|
||||
const headers = new Headers(response.headers);
|
||||
headers.set('Content-Disposition', `inline; filename="${encodedFileName}"`);
|
||||
headers.set('Content-Disposition', `inline; filename="${encodedFileName}"; filename*=UTF-8''${encodedFileName}`);
|
||||
if (fileType) {
|
||||
headers.set('Content-Type', fileType);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,11 @@ export async function onRequestPost(context) { // Contents of context object
|
||||
sendFunction = {'url': 'sendAnimation', 'type': 'animation'};
|
||||
}
|
||||
|
||||
// 从参数中获取serverCompress,如果为false,则使用sendDocument接口
|
||||
if (url.searchParams.get('serverCompress') === 'false') {
|
||||
sendFunction = {'url': 'sendDocument', 'type': 'document'};
|
||||
}
|
||||
|
||||
// 优先从请求 URL 获取 authCode
|
||||
let authCode = url.searchParams.get('authCode');
|
||||
// 如果 URL 中没有 authCode,从 Referer 中获取
|
||||
@@ -210,6 +215,10 @@ function getFile(response) {
|
||||
return getFileDetails(response.result.video);
|
||||
}
|
||||
|
||||
if (response.result.audio) {
|
||||
return getFileDetails(response.result.audio);
|
||||
}
|
||||
|
||||
if (response.result.document) {
|
||||
return getFileDetails(response.result.document);
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/logo.png"><title>Sanyue ImgHub</title><script defer="defer" src="/js/app.40c62b88.js"></script><link href="/css/app.def7ef9b.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but sanyue_imghub doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/logo.png"><title>Sanyue ImgHub</title><script defer="defer" src="/js/app.5e5c7c7e.js"></script><link href="/css/app.def7ef9b.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but sanyue_imghub doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
BIN
index.html.gz
BIN
index.html.gz
Binary file not shown.
2
js/538.4708c14c.js
Normal file
2
js/538.4708c14c.js
Normal file
File diff suppressed because one or more lines are too long
BIN
js/538.4708c14c.js.gz
Normal file
BIN
js/538.4708c14c.js.gz
Normal file
Binary file not shown.
1
js/538.4708c14c.js.map
Normal file
1
js/538.4708c14c.js.map
Normal file
File diff suppressed because one or more lines are too long
BIN
js/538.4708c14c.js.map.gz
Normal file
BIN
js/538.4708c14c.js.map.gz
Normal file
Binary file not shown.
2
js/782.76212525.js
Normal file
2
js/782.76212525.js
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";(self["webpackChunksanyue_imghub"]=self["webpackChunksanyue_imghub"]||[]).push([[782],{6782:function(e,s,a){a.r(s),a.d(s,{default:function(){return k}});var n=a(47),t=(a(5331),a(9648),a(2105)),o=(a(9092),a(6768)),r=a(5130);const i={class:"login"},u={class:"login-container"},l={class:"input-container"},c={class:"input-container"};function d(e,s,a,d,p,m){const h=t.WK,k=n.S2;return(0,o.uX)(),(0,o.CE)("div",i,[(0,o.Lk)("div",u,[s[5]||(s[5]=(0,o.Lk)("h1",null,"AdminLogin",-1)),(0,o.Lk)("div",l,[s[2]||(s[2]=(0,o.Lk)("a",{class:"input-name"},"用户名:",-1)),(0,o.bF)(h,{modelValue:p.username,"onUpdate:modelValue":s[0]||(s[0]=e=>p.username=e),placeholder:"请输入用户名",class:"username-input"},null,8,["modelValue"])]),(0,o.Lk)("div",c,[s[3]||(s[3]=(0,o.Lk)("a",{class:"input-name"},"密码:",-1)),(0,o.bF)(h,{modelValue:p.password,"onUpdate:modelValue":s[1]||(s[1]=e=>p.password=e),placeholder:"请输入密码",class:"password-input",type:"password","show-password":"",onKeyup:(0,r.jR)(m.login,["enter","native"])},null,8,["modelValue","onKeyup"])]),(0,o.bF)(k,{class:"submit",type:"primary",onClick:m.login},{default:(0,o.k6)((()=>s[4]||(s[4]=[(0,o.eW)("登录")]))),_:1},8,["onClick"])])])}a(4114),a(4979);var p={data(){return{password:"",username:""}},methods:{async login(){const e=btoa(`${this.username}:${this.password}`);try{const s=await fetch("/api/manage/check",{method:"GET",headers:{Authorization:`Basic ${e}`},credentials:"include"});401===s.status?this.$message.error("用户名或密码错误"):200===s.status?(this.$store.commit("setCredentials",e),this.$router.push("/dashboard")):this.$message.error("用户名或密码错误")}catch(s){this.$message.error("服务器错误")}}}},m=a(1241);const h=(0,m.A)(p,[["render",d],["__scopeId","data-v-50aaab2d"]]);var k=h}}]);
|
||||
//# sourceMappingURL=782.76212525.js.map
|
||||
BIN
js/782.76212525.js.gz
Normal file
BIN
js/782.76212525.js.gz
Normal file
Binary file not shown.
1
js/782.76212525.js.map
Normal file
1
js/782.76212525.js.map
Normal file
File diff suppressed because one or more lines are too long
BIN
js/782.76212525.js.map.gz
Normal file
BIN
js/782.76212525.js.map.gz
Normal file
Binary file not shown.
2
js/880.cf9a61e3.js
Normal file
2
js/880.cf9a61e3.js
Normal file
File diff suppressed because one or more lines are too long
BIN
js/880.cf9a61e3.js.gz
Normal file
BIN
js/880.cf9a61e3.js.gz
Normal file
Binary file not shown.
1
js/880.cf9a61e3.js.map
Normal file
1
js/880.cf9a61e3.js.map
Normal file
File diff suppressed because one or more lines are too long
BIN
js/880.cf9a61e3.js.map.gz
Normal file
BIN
js/880.cf9a61e3.js.map.gz
Normal file
Binary file not shown.
2
js/986.e373666b.js
Normal file
2
js/986.e373666b.js
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";(self["webpackChunksanyue_imghub"]=self["webpackChunksanyue_imghub"]||[]).push([[986],{986:function(s,t,e){e.r(t),e.d(t,{default:function(){return b}});var i=e(47),a=(e(5331),e(9648),e(2105)),n=(e(9092),e(6768)),l=e(5130);const o={class:"login"},r={class:"login-container"};function g(s,t,e,g,c,u){const p=a.WK,h=i.S2;return(0,n.uX)(),(0,n.CE)("div",o,[t[3]||(t[3]=(0,n.Lk)("img",{id:"bg1",class:"background-image1",alt:"Background Image"},null,-1)),t[4]||(t[4]=(0,n.Lk)("img",{id:"bg2",class:"background-image2",alt:"Background Image"},null,-1)),(0,n.Lk)("div",r,[t[2]||(t[2]=(0,n.Lk)("h1",null,"Login",-1)),(0,n.bF)(p,{class:"password-input",modelValue:c.password,"onUpdate:modelValue":t[0]||(t[0]=s=>c.password=s),placeholder:"输入认证码,若未设置留空即可~",type:"password","show-password":"",onKeyup:(0,l.jR)(u.login,["enter","native"])},null,8,["modelValue","onKeyup"]),(0,n.bF)(h,{class:"submit",type:"primary",onClick:u.login},{default:(0,n.k6)((()=>t[1]||(t[1]=[(0,n.eW)("登录")]))),_:1},8,["onClick"])])])}e(4114);var c=e(4570),u=e.n(c),p=e(4373),h=e(782),d={data(){return{password:"",writtenPass:"",bingWallPaperIndex:0,customWallPaperIndex:0}},computed:{...(0,h.L8)(["userConfig","bingWallPapers"]),bkInterval(){return this.userConfig?.bkInterval||3e3},bkOpacity(){return this.userConfig?.bkOpacity||1}},mounted(){const s=document.getElementById("bg1"),t=document.getElementById("bg2");"bing"===this.userConfig?.loginBkImg?this.$store.dispatch("fetchBingWallPapers").then((()=>{s.src=this.bingWallPapers[this.bingWallPaperIndex]?.url,s.onload=()=>{s.style.opacity=this.bkOpacity},setInterval((()=>{let e=0!=s.style.opacity?s:t,i=0!=s.style.opacity?t:s;e.style.opacity=0,this.bingWallPaperIndex=(this.bingWallPaperIndex+1)%this.bingWallPapers.length,i.src=this.bingWallPapers[this.bingWallPaperIndex]?.url,i.onload=()=>{i.style.opacity=this.bkOpacity}}),this.bkInterval)})):this.userConfig?.loginBkImg instanceof Array&&this.userConfig?.loginBkImg?.length>1?(s.src=this.userConfig.loginBkImg[this.customWallPaperIndex],s.onload=()=>{s.style.opacity=this.bkOpacity},setInterval((()=>{let e=0!=s.style.opacity?s:t,i=0!=s.style.opacity?t:s;e.style.opacity=0,this.customWallPaperIndex=(this.customWallPaperIndex+1)%this.userConfig.loginBkImg.length,i.src=this.userConfig.loginBkImg[this.customWallPaperIndex],i.onload=()=>{i.style.opacity=this.bkOpacity}}),this.bkInterval)):this.userConfig?.loginBkImg instanceof Array&&1==this.userConfig?.loginBkImg?.length?(s.src=this.userConfig.loginBkImg[0],s.onload=()=>{s.style.opacity=this.bkOpacity}):(s.src=e(732),s.onload=()=>{s.style.opacity=this.bkOpacity})},methods:{login(){""===this.password?this.writtenPass="unset":this.writtenPass=this.password,p.A.post("/login",{authCode:this.password}).then((s=>{200===s.status?(u().set("authCode",this.writtenPass,"14d"),this.$router.push("/"),this.$message.success("登录成功~")):this.$message.error("登录失败,请检查认证码是否正确~")})).catch((s=>{this.$message.error("登录失败,请检查认证码是否正确~")}))}}},y=e(1241);const m=(0,y.A)(d,[["render",g],["__scopeId","data-v-1774635e"]]);var b=m},732:function(s,t,e){s.exports=e.p+"img/background.ea1b7ee7.jpg"}}]);
|
||||
//# sourceMappingURL=986.e373666b.js.map
|
||||
BIN
js/986.e373666b.js.gz
Normal file
BIN
js/986.e373666b.js.gz
Normal file
Binary file not shown.
1
js/986.e373666b.js.map
Normal file
1
js/986.e373666b.js.map
Normal file
File diff suppressed because one or more lines are too long
BIN
js/986.e373666b.js.map.gz
Normal file
BIN
js/986.e373666b.js.map.gz
Normal file
Binary file not shown.
46
js/app.5e5c7c7e.js
Normal file
46
js/app.5e5c7c7e.js
Normal file
File diff suppressed because one or more lines are too long
BIN
js/app.5e5c7c7e.js.gz
Normal file
BIN
js/app.5e5c7c7e.js.gz
Normal file
Binary file not shown.
1
js/app.5e5c7c7e.js.map
Normal file
1
js/app.5e5c7c7e.js.map
Normal file
File diff suppressed because one or more lines are too long
BIN
js/app.5e5c7c7e.js.map.gz
Normal file
BIN
js/app.5e5c7c7e.js.map.gz
Normal file
Binary file not shown.
Reference in New Issue
Block a user