在 Next.js中上传图片到阿里云 OSS 可以按照以下步骤进行:
一、安装依赖
首先安装阿里云 OSS 的 SDK:
npm i ali-oss
npm i -D @types/ali-oss
npm i -D @types/ali-oss
二、配置阿里云OSS
在src目录下中创建一个用于配置 OSS 的文件,比如ossConfig.ts
import OSS from 'ali-oss';
const ossClient = new OSS({
region: 'your-region',
accessKeyId: 'your-access-key-id',
accessKeySecret: 'your-access-key-secret',
bucket: 'your-bucket-name',
endpoint: 'your-endpoint',
});
export default ossClient;
const ossClient = new OSS({
region: 'your-region',
accessKeyId: 'your-access-key-id',
accessKeySecret: 'your-access-key-secret',
bucket: 'your-bucket-name',
endpoint: 'your-endpoint',
});
export default ossClient;
将your-region、your-access-key-id、your-access-key-secret、your-bucket-name和your-endpoint替换为你的实际阿里云 OSS 配置信息。
三、上传图片
下面例子使用了hono.js来作为api路由
1.创建一个处理上传的 API 路由,比如在app/api/[[...route]]/upload.js文件中:
import { Hono } from "hono";
import { format } from "date-fns";
import { v4 as uuid } from "uuid";
import ossClient from '@/ossConfig';
const app = new Hono();
app.post('/uploadToOSS', async (c) => {
const body = await c.req.parseBody();
// console.log(body);
const file = body['image'] as File;
// console.log(file);
//限制只能上传图片类型
const fileType = file.type;
if (!fileType.startsWith('image/')) {
return c.json({ status: 1, msg: '只能上传图片' });
}
const fileName = `images/${format(new Date(), 'yyyy-MM-dd')}/${uuid()}_${file.name}`;
// console.log(fileName);
try {
// 将文件转换为 Buffer
const buffer = await file.arrayBuffer();
const result = await ossClient.put(fileName, Buffer.from(buffer));
// console.log(result);
if (result.res.status === 200) {
return c.json({ status: 0, msg: '图片上传成功', url: result.url });
} else {
return c.json({ status: 1, msg: '图片上传失败' });
}
} catch (error) {
return c.json({ status: 1, msg: '图片上传失败', error: error });
}
});
export default app;
import { format } from "date-fns";
import { v4 as uuid } from "uuid";
import ossClient from '@/ossConfig';
const app = new Hono();
app.post('/uploadToOSS', async (c) => {
const body = await c.req.parseBody();
// console.log(body);
const file = body['image'] as File;
// console.log(file);
//限制只能上传图片类型
const fileType = file.type;
if (!fileType.startsWith('image/')) {
return c.json({ status: 1, msg: '只能上传图片' });
}
const fileName = `images/${format(new Date(), 'yyyy-MM-dd')}/${uuid()}_${file.name}`;
// console.log(fileName);
try {
// 将文件转换为 Buffer
const buffer = await file.arrayBuffer();
const result = await ossClient.put(fileName, Buffer.from(buffer));
// console.log(result);
if (result.res.status === 200) {
return c.json({ status: 0, msg: '图片上传成功', url: result.url });
} else {
return c.json({ status: 1, msg: '图片上传失败' });
}
} catch (error) {
return c.json({ status: 1, msg: '图片上传失败', error: error });
}
});
export default app;
2.创建一个前端上传页面:
"use client";
import { ChangeEvent, FormEvent,useState } from 'react';
const uploadPage = () => {
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const handleFileChange = (e:ChangeEvent<HTMLInputElement>) => {
if(e.target.files){
setSelectedFile(e.target.files[0]);
}
};
const handleSubmit = async (e:FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData();
formData.append('image', selectedFile!);
const response = await fetch('/api/upload/uploadToOSS', {
method: 'POST',
body: formData,
});
const data = await response.json();
// 处理上传成功后的返回结果
console.log(data);
if(data.status === 0){
alert("上传成功");
//返回的图片地址是data.url
}else{
alert("上传失败");
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="file" onChange={handleFileChange} />
<button type="submit">上传</button>
</form>
</div>
);
};
export default uploadPage;
import { ChangeEvent, FormEvent,useState } from 'react';
const uploadPage = () => {
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const handleFileChange = (e:ChangeEvent<HTMLInputElement>) => {
if(e.target.files){
setSelectedFile(e.target.files[0]);
}
};
const handleSubmit = async (e:FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData();
formData.append('image', selectedFile!);
const response = await fetch('/api/upload/uploadToOSS', {
method: 'POST',
body: formData,
});
const data = await response.json();
// 处理上传成功后的返回结果
console.log(data);
if(data.status === 0){
alert("上传成功");
//返回的图片地址是data.url
}else{
alert("上传失败");
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="file" onChange={handleFileChange} />
<button type="submit">上传</button>
</form>
</div>
);
};
export default uploadPage;
这样就可以在 Next.js 14 中实现将图片上传到阿里云 OSS。
四、实现点击按钮直接上传
如果不想先选择文件,然后再点击上传按钮上传。想直接点击按钮,用户选择完文件就自动上传,可以按照下面方法来操作:
将用户选择文件事件和上传事件放到一个方法里面
代码如下:
import { ChangeEvent } from "react";
const uploadPage = () => {
const handleFileChange = async (e: ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) return;
const file = e.target.files[0];
if (!file) return;
// console.log(file);
const formData = new FormData();
formData.append('image', file!);
const response = await fetch('/api/upload/uploadToOSS', {
method: 'POST',
body: formData,
});
const data = await response.json();
// 处理上传成功后的返回结果
// console.log(data);
if (data.status === 0) {
alert("上传成功");
//返回的图片地址是data.url
} else {
alert("上传失败");
}
};
return (
<div>
<label
htmlFor="upload"
className="flex justify-center items-center w-full
text-white text-sm font-medium
bg-blue-600 hover:bg-blue-600 py-2
rounded-md cursor-pointer">
上传图片
<input id="upload" type="file" onChange={handleFileChange} className="hidden" />
</label>
</div>
)
}
export default uploadPage;
const uploadPage = () => {
const handleFileChange = async (e: ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) return;
const file = e.target.files[0];
if (!file) return;
// console.log(file);
const formData = new FormData();
formData.append('image', file!);
const response = await fetch('/api/upload/uploadToOSS', {
method: 'POST',
body: formData,
});
const data = await response.json();
// 处理上传成功后的返回结果
// console.log(data);
if (data.status === 0) {
alert("上传成功");
//返回的图片地址是data.url
} else {
alert("上传失败");
}
};
return (
<div>
<label
htmlFor="upload"
className="flex justify-center items-center w-full
text-white text-sm font-medium
bg-blue-600 hover:bg-blue-600 py-2
rounded-md cursor-pointer">
上传图片
<input id="upload" type="file" onChange={handleFileChange} className="hidden" />
</label>
</div>
)
}
export default uploadPage;