前端-后端交互(文件从前端上传阿里云OSS)
前端fetch
发送 HTTP 请求:
ES8中提供的新的异步API操作 ,fetch,await async:
在ES8 (ECMAScript 2017) 中,引入了 async
和 await
关键字,这是JavaScript中处理异步操作的一种新方法。这两个关键字旨在简化使用承诺(promises)执行异步操作时的语法。它们帮助开发者以一种更接近同步编程的方式来编写异步代码,从而提高代码的可读性和维护性。
async
async
函数是一种特殊类型的函数,用于定义异步函数,它始终返回一个 Promise
对象。async
函数内部可以使用 await
表达式,这有助于暂停函数的执行,直到等待的 Promise
解决
await
await
关键字用于等待 Promise
解决,并暂停 async
函数的执行,直到 Promise
完成(resolved)。使用 await
可以以一种更线性、更同步的方式编写异步代码,从而避免回调地狱。
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>基于fetch的上传图片、文件到OSS</title>
<script>
function $(id) {
return document.getElementById(id);
}
function reg() {
let file =$("file").files; //同名的file元素有多个
//具体流程 第一步
const formData=new FormData(); // 表示以表单形式构建参数
// formData.append( "file", file);
for(let i = 0; i < file.length; i++) {
formData.append("file"+i, file[i]); // 将文件对象添加到 formData 中
}
// 第四步 向后端传数据 , 提交数据到后端
const postData = async (url, data) => {
try {
const response = await fetch(url, {
method: 'POST',
//参数 : 因为有图片,文件,所以不能以json格式传数据
body: data
});
// 前后端关键地方 前后端分隔的地方 暂停 等后端处理完前端传的数据 接收来自后端的数据 返回出去
const result = await response.json(); //将响应体解析为 JSON 格式
return result; //此result是一个包含了jsonmodel的promise对象
} catch (error) {
console.error('Error sending POST request:', error);
}
};
//第二步 设置要调的Servlet 并传一个op判断调用的方法
const apiUrl = 'FileToOSSText.action?op=regFile';
//第三步 传递参数
const pro = postData( apiUrl , formData ); //pro就是执行后的promise对象
//第五步 接收后端数据 进行判断
pro.then(jsonobj => {
if (jsonobj.code == 1) {
$("resultdiv").innerHTML = "<b>文件上传成功</b> <br />链接地址:"+jsonobj.obj;
$('myImg').src=jsonobj.obj ;
} else {
$("resultdiv").innerHTML = "<b>文件上传失败</b> 原因:" + jsonobj.error;
}
});
}
</script>
</head>
<body>
选择需要上传的文件:<input type="file" name="file" id="file" multiple> <br />
<input type="button" id="btn" value="上传" onclick="reg()"/>
<div id="resultdiv"></div>
<h2>如果是图片则显示在下面:</h2>
<img src="" id="myImg" width="100px"height="100px">
</body>
</html>
后端Servlet 接收(使用容器 Apache Tomcat)
Java Servlet
Java Servlet 是 Java EE 规范中的一部分,用于处理 Web 请求和响应。你可以编写自己的 Servlet 类来处理来自前端的 HTTP 请求,然后部署到 Servlet 容器(如 Apache Tomcat 或者 Jetty)中运行。
1 接收前端发来的请求,调用doGet()方法,激活regFile()函数
import com.google.gson.Gson;
import com.yc.Servlet.JsonModel;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
public abstract class BaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String op = req.getParameter("op"); //取值 op=regFile
JsonModel jm = new JsonModel(); //用来保存要运行后的信息 并 返回到前端
try {
if (op == null || "".equals(op)) {
// out.println( "{code:0,error:'没有op参数'}" );
jm.setCode(0);
jm.setError("op参数不能为空..");
writeJson(jm,resp);
return;
}
/// 反 射
Method[] methods = this.getClass().getDeclaredMethods();//取子类中的方法
for (Method m:methods){
if ( m.getName().equals( op ) ) { // 判断有没有 regFile方法
m.invoke(this, req, resp);//激活对应函数 regFile
}
}
} catch (Exception e) {
e.printStackTrace();
jm.setCode(0);
jm.setError( e.getMessage() );
writeJson(jm,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8"); // 响应流的编码
resp.setContentType("text/html;charset=utf-8");
super.service(req, resp);//判断调用doGet()还是doPost()方法
}
//***** 最后要执行的函数 返回信息到前端
//*** 后端传数据到前端 关键地方 *** 以json格式传数据到前端
protected void writeJson( JsonModel jm , HttpServletResponse resp) throws IOException {
resp.setContentType("text/json;charset=utf-8");
PrintWriter out = resp.getWriter();
Gson g = new Gson();
out.println( g.toJson( jm )); ///后端 把 运行情况 以json类型传出到前端
out.flush();
out.close();
}
}
2 对文件进行处理,并传文件信息到上传工具
import com.yc.Servlet.JsonModel;
import com.yc.utils.BaseServlet;
import com.yc.utils.UploadToOSS;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
@WebServlet("/FileToOSSText.action")
@MultipartConfig(fileSizeThreshold = 1024*1024 , maxFileSize = 1024*1024*5 , maxRequestSize = 1024*1024*5*5)
public class FileToOSSText extends BaseServlet {
public void regFile(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
JsonModel jm = new JsonModel();
Collection<Part> parts = req.getParts(); // 获取所有部分
try {
for (Part part : parts) {
if (part.getContentType() != null) { // 检查部分是否为文件
String fileName = part.getSubmittedFileName(); // 获取文件名
InputStream fileContent = part.getInputStream(); // 获取文件内容的输入流
String url = UploadToOSS.uploadFileOSS( fileName , fileContent );//调用上传到OSS的函数
if ( "0".equals(url) ){ //上传失败
jm.setCode(0);
jm.setError("上传失败。。。");
super.writeJson( jm , resp );
return;
}else { //上传成功
jm.setObj(url);
jm.setCode(1);
}
}
}
} catch (Exception ex) {
throw new ServletException(ex);
} finally {
super.writeJson(jm,resp);
System.out.println("OSS close Success");
UploadToOSS.close(); // 最终,无论上传成功还是失败,都关闭OSS客户端实例以释放资源。
}
}
}
3 上传文件到阿里云OSS,并返回URL(访问域名)
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyuncs.exceptions.ClientException;
import java.io.InputStream;
public class UploadToOSS {
//OSS客户端实例
static OSS ossClient = null;
public static String uploadFileOSS(String fileKey, InputStream inputStream) throws ClientException {
// 阿里云OSS服务的Endpoint。 服务的访问域名,指定了阿里云OSS服务的网络节点
String endpoint = "http://oss-cn-beijing.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 你的阿里云OSS存储桶名称。填写Bucket名称,
String bucketName = "xin-qiu";
// OSS中的文件键(Key),即上传后的文件名。
// String fileKey = "qqq.jpg"; // 保存到OSS的文件名
// 本地系统中的文件路径,用于找到你想上传的文件。
// String filePath = "C:/Users/DELL/OneDrive/桌面/图片/二次元/qqq.jpg"; // 本地文件路径
// 使用OSSClientBuilder构建一个OSS客户端实例。
ossClient = new OSSClientBuilder().build(endpoint,credentialsProvider);
try {
// 创建一个文件输入流,用于读取本地文件。
// FileInputStream inputStream = new FileInputStream(filePath);
// 调用OSS客户端的putObject方法上传文件。传入存储桶名、文件键和文件输入流。
ossClient.putObject(bucketName, fileKey, inputStream);
System.out.println("上传成功");
//返回出去并保存到数据库 : https://xin-qiu.oss-cn-beijing.aliyuncs.com/cx.png
return "https:/xin-qiu.oss-cn-beijing.aliyuncs.com/"+fileKey;//上传成功 把 访问域名返回出去
} catch (Exception e) {
System.out.println("文件未找到:" + e.getMessage());
return "0"; //失败返回 0
}
}
public static void close() {
// 最终,无论上传成功还是失败,都关闭OSS客户端实例以释放资源。
ossClient.shutdown();
}
}
4 最后调用BaseServlet类中的 writeJson() 函数把结果以json格式传到前端
//***** 最后要执行的函数 返回信息到前端
//*** 后端传数据到前端 关键地方 *** 以json格式传数据到前端
protected void writeJson( JsonModel jm , HttpServletResponse resp) throws IOException {
resp.setContentType("text/json;charset=utf-8");
PrintWriter out = resp.getWriter();
Gson g = new Gson();
out.println( g.toJson( jm )); ///后端 把 运行情况 以json类型传出到前端
out.flush();
out.close();
}
保存运行情况类
import lombok.Data;
import java.io.Serializable;
@Data
public class JsonModel implements Serializable {
private Integer code; //响应码 : 0:表示失败 1:表示成功
private Object obj;
private String error;
}
需要的依赖
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.80</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.1.0</version>
</dependency>