前端XMLHttpRequest、Fetch API、Axios实现文件上传、下载方法及后端Spring文件服务器处理方法

littleshimmer 2024-08-01 16:03:02 阅读 83

前言

本文总结Web应用开发中文件上传、下载的方法,即从前端表单输入文件并封装表单数据,然后请求后端服务器的处理过程;从基础的JavaScript中XmlHttpRequest对象、Fetch API实现上传、下载进行说明,并给出了前端常用的axios库的请求方式,然后给出了后端Spring实现文件服务器的方法,其中就文件上传中遇到的大小限制、跨域请求、外链请求等关键点进行了说明

上传文件

前端上传请求发起的方式:若不依赖其他库常使用XMLHttpRequest、Fetch API上传方式,若使用第三方库可用Axios请求上传

后端文件服务器的几种处理方式:

文保存到磁盘目录

文件存取请求直接根据url地址得出文件所在磁盘目录位置,访问速度快

文件直接保存到数据库

若文件比较大,影响数据库处理性能,但相比保存到磁盘目录的方法可以确保数据更安全可靠性

文件二次请求上传至第三方服务器

后端将接收的表单数据按照第三方接口封装进行请求上传

XMLHttpRequest文件上传

1.表单输入文件

<code><!-- 设置multiple属性时可选择多个文件,可在读取文件时使用onchange监听读取到文件内容后预览、或立即上传,也可以单独用一个按钮事件控制上传 -->

<input type="file" multiple id="fileInput" onchange="onShowTextContent(event)"></input>code>

<pre id="fileContent"></pre>code>

<button onclick="uploadFile()">上传文件</button>code>

预览文本内容并显示方法

<script>

function onShowTextContent(event) { // 预览文本内容并显示方法

const file = event.target.files[0];

if (file && file.type.startsWith("text/plain") ) {

const reader = new FileReader();

// 定义文件读取完成后的处理逻辑

reader.onload = function (e) {

const fileContent = e.target.result;

// 显示文本内容

document.getElementById('fileContent').textContent = fileContent;

};

// 读取文件为文本内容

reader.readAsText(file);

} else {

console.error('No file selected');

}

}

</script>

2.XMLHttpRequest上传文件

XMLHttpRequest对象简记为XHR,一个内置的浏览器对象,提供简单的方式来发送和接收从 URL 的数据而无需刷新整个页面,这使得它成为 AJAX(Asynchronous JavaScript and XML)编程的核心技术之一

AJAX是一种在 Web 应用中通过异步发送 HTTP 请求向服务器获取内容,并使用这些新内容更新页面中相关的部分,而无需重新加载整个页面的 Web 开发技术,这可以让网页更具有响应性,由于这种技术在现代Web开发中太过常见以至于AJAX这个术语很少被使用到

XMLHttpRequest具有广泛的兼容性,几乎所有浏览器都支持,包括老版本浏览器,而Fetch API 但在某些旧浏览器(如 IE)中不支持

function uploadFile() {

let fileInput = document.getElementById("fileInput"); // 获得input文件输入的引用

let files = fileInput.files;

if (files.length === 0) {

return; // input节点的files是一个文件列表,若 files.length === 0 表示未选择文件,需要跳过

}

let formData = new FormData(); // 创建表单数据对象,封装文件

for (let file of files) {

// file有一些属性常用于校验,如 file.name 文件名称,file.size 文件字节大小,file.type表示文件类型

formData.append("files", file);

}

let request = new XMLHttpRequest(); // 创建一个http请求

let url = "http://127.0.0.1:7999/file/upload";

request.open("POST", url, true); // 参数1为请求方式,参数2为上传服务器地址,参数3取true表示异步

request.onload = function () {

if (request.status === 200) {

console.log("上传完成:", request.responseText);

} else {

console.log("上传出错:", request.statusText);

}

};

request.onerror = function () {

console.log("Error:", request.statusText);

};

request.send(formData); // 发送表单文件数据

}

3. 后端接收文件和保存

先对上传的文件大小、接收文件的类型做判断,然后将原始文件名称、大小、内容类型、存储位置等信息到数据库以提供分类、统计分析

Controller层接收上传的文件

// @RequestParam 注解标注表单的参数名,与form表单一致,若该注解缺省则默认参数名称为"multipart"

// 入参 MultipartFile[] 数组表示接受多个文件,若写为 MultipartFile对象则只会接受第1个文件,cconsumes 指定匹配请求头 "content-type"

@PostMapping(value="/upload/list",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)code>

public Map<String,Object> uploadFileList(@RequestParam("files") MultipartFile[] files);

Service层本地存储文件

// controller层调用的文件保存方法,对 MultipartFile[] files 中每个对象处理,判断文件上传个数等

public Map<String,Object> saveMultipartFile(MultipartFile multipartFile) throws IOException {

Map<String, Object> results = new HashMap<>();

if (multipartFile.getSize() >= 1024 * 1024 * 10) {

throw new RuntimeException("文件大小超过了最大限制10M");

}

// multipartFile.getContentType() 获取内容类型

final String oriName = multipartFile.getOriginalFilename();

// 原始文件名不能保证唯一性,需要生成一个唯一文件名,此处仅简单示例,实际开发中文件名称需要确保唯一性

String newName = System.currentTimeMillis() + oriName.substring(oriName.lastIndexOf(".")); //

String fullPath = System.getProperty("user.dir") + "/" + newName;

final InputStream inputStream = multipartFile.getInputStream();

File file = new File(fullPath);

// 也可以直接使用 multipartFile.transferTo(file);

if (file.createNewFile()) {

FileCopyUtils.copy(inputStream, Files.newOutputStream(file.toPath()));

}

// 返回一些有用的信息,若是图片需要返回url等

results.put("url","http://127.0.0.1:7999/file/"+newName);

return results;

}

后端转发请求上传到第三方

public Result<FileUploadResponse> uploadImageForward(MultipartFile multipartFile) throws IOException {

MultiValueMap request = new LinkedMultiValueMap(1);

ByteArrayResource byteArrayResource = new ByteArrayResource(multipartFile.getBytes()) {

@Override // 需要覆盖默认的方法,不然无法获取名称

public String getFilename() {

return multipartFile.getOriginalFilename();

}

};

// 此处从multipartFile获取byte[],如果是上传本地文件可以使用io获取byte[]

request.add("fileName", byteArrayResource);

String uploadUrl = this.serverBaseUrl+"/upload"; // 假如这是第三方文件上传地址

FileUploadResponse response = restTemplate.postForObject(uploadUrl, request, FileUploadResponse.class);

return new Result<>(response);

}

4.文件上传大小配置

在 Spring Boot 项目中,可通过配置文件或编程方式来设置文件上传的大小

配置文件方式(application.properties 或 application.yml)

application.properties

# 设置单个文件的最大大小为10MB(默认情况下为1MB)

spring.servlet.multipart.max-file-size=10MB

# 设置整个请求的最大大小为10MB(默认情况下是10MB)

spring.servlet.multipart.max-request-size=10MB

application.yml

spring:

servlet:

multipart:

max-file-size: 10MB

max-request-size: 10MB

编程方式

可进行更细粒度的控制,可以通过编程配置 MultipartConfigElement实现

@Configuration

public class ServletMultipartConfig {

// 配置文件中添加示例:spring.server.MaxFileSize=1MB

@Value("${spring.server.maxFileSize}")

private DataSize maxFileSize;

// 指定单个文件最大尺寸,如果超过这个大小,后端将不会接受该请求,前端会手到错误:CodeDetails Error: Request Entity Too Large

@Bean

public MultipartConfigElement multipartConfigElement() {

// log.info("MaxFileSize="+maxFileSize.toMegabytes());

MultipartConfigFactory factory = new MultipartConfigFactory();

factory.setMaxFileSize(maxFileSize); // 但个文件最大大小

factory.setMaxRequestSize(maxFileSize); // 整个请求的最大大小

return factory.createMultipartConfig();

}

}

5.后端跨域请求配置

文件上传在跨域的情况下会上传失败,因此有必要设置服务器的跨域请求规则

springboot的配置类中添加跨域请求配置,以拦截器方式实现为例:

@Configuration

public class WebConfig implements WebMvcConfigurer {

@Bean

public HandlerInterceptor accessInterceptor() {

return new HandlerInterceptor(){

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

// 若请求头设置了Access-Control-Allow-Credentials为true,那"Access-control-Allow-Origin不能使用通配符*,而必须要使用确切的值code>

response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));

response.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE,HEAD,PATCH");

// 若前端传送了自定义的请求头而没有在这里面设置,某些情况下则会提示跨域请求错误:not allowed by Access-Control-Allow-Headers in preflight response.

response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");

response.setHeader("Access-Control-Allow-Credentials", "true"); // 前端请求设置credentials: 'include', 这里就必须设置为true

response.setHeader("Access-Control-Max-Age", "3600");

// 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态

if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {

response.setStatus(HttpStatus.OK.value());

return false;

}

return true;

}

};

}

@Override

public void addInterceptors(InterceptorRegistry registry) { // 添加拦截器

registry.addInterceptor(this.accessInterceptor())

.excludePathPatterns("/error")

.excludePathPatterns("/webjars/**", "/v2/api-docs/**");

}

}

与上述拦截器实现的效果一样,也可以采用过滤器实现跨域请求配置:

@Bean // 注册过滤器

public FilterRegistrationBean<CustomCorsFilter> customCorsFilterFilterRegistrationBean(){

FilterRegistrationBean<CustomCorsFilter> registrationBean = new FilterRegistrationBean<>(this.customCorsFilter());

registrationBean.setOrder(-1); // 设置序号,越小优先级越高越靠前执行,确保在其他业务处理之前执行到

registrationBean.addUrlPatterns("/*");

return registrationBean;

}

@Bean // 确保过滤器被加入到ioc容器

public CustomCorsFilter customCorsFilter(){

return new CustomCorsFilter();

}

// 实现一个过滤器,继承Filter接口,覆盖doFilter方法

public static class CustomCorsFilter implements Filter{

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

HttpServletResponse response = (HttpServletResponse) servletResponse;

HttpServletRequest request = (HttpServletRequest) servletRequest;

response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));

response.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE,HEAD,PATCH");

// 若前端传送了自定义的请求头而没有在这里面设置,某些情况下则会提示跨域请求错误:not allowed by Access-Control-Allow-Headers in preflight response.

response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");

response.setHeader("Access-Control-Allow-Credentials", "true"); // 前端请求设置credentials: 'include', 这里就必须设置为true

response.setHeader("Access-Control-Max-Age", "3600"); // 设置 Access-Control-Max-Age 为 3600,表示预检请求的结果可以缓存 3600 秒(即 1 小时),在此期间浏览器不需要为相同的跨域请求再次发送预检请求

filterChain.doFilter(servletRequest,servletResponse);

}

}

Axios文件上传

Axios是一个基于promise的http库,可以用于Node.js中,可兼容所有主流浏览器,该库提供了简洁的API用于执行Http请求,可拦截请求和响应,转换请求和响应请求数据等

引入axios库,然后使用axios提供的方法进行文件上传,后端接收文件的方法与上述一致

<!-- 引入axios库,实际开发中建议用 npm install axios 安装到本地 -->

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>code>

<script>

function uploadFileByAxios() {

const files = document.getElementById('fileInput').files;

const formData = new FormData();

for (let i = 0; i < files.length; i++) {

formData.append('files', files[i]);

}

let httpHeaders = { };

// 表单Content-Type可以不用设置,默认就是 httpHeaders['Content-Type'] = 'multipart/form-data';

// let uploadUrl = "http://127.0.0.1:7999/file/upload";

axios.post(uploadUrl, formData, { headers: httpHeaders })

.then(response => {

console.log('Files uploaded successfully:', response.data);

})

.catch(error => {

console.error('Error uploading files:', error);

});

}

</script>

Fetch API实现文件上传

Fetch API 是一个用于现代Web应用执行网络请求的内置接口,它在XMLHttpRequest 之后出现

Fetch API 基于 Promise,可以使用链式结构来处理请求和响应,它提供了一种更简单、更灵活的方式来进行异步请求

function uploadFilesByFetch() {

let files = document.getElementById('fileInput').files;

let formData = new FormData();

for (let i = 0; i < files.length; i++) {

formData.append('files', files[i]);

}

let uploadUrl = uploadUrl = "http://127.0.0.1:7999/file/upload";

fetch(uploadUrl, {

method: 'POST',

body: formData

})

.then(response => {

if (!response.ok) {

throw new Error('Network response was not ok ' + response.statusText);

}

return response.json();

})

.then(data => {

console.log('Files uploaded successfully:', data);

})

.catch(error => {

console.error('Error uploading files:', error);

});

}

下载文件

下载文件包括交互事件请求下载、超链接下载

XMLHttpRequest文件下载

1.下载按钮事件

<div>

<label>下载地址:</label>

<input type="text" id="downloadUrl" value="http://127.0.0.1:7999/file/download/filename"></input>code>

</div>

<button onclick="downloadFileByXHR()">XMLHttpRequest下载</button>code>

<!-- 可以隐藏一个a标签,通过其他按钮事件触发 -->

<button onclick="downloadLink()">超链接下载方式</button><a id="link" style="display: none;"></a>code>

<!-- 超链接下载方法:直接指定带有href属性的a标签点击即可下载 -->

<a href="http://127.0.0.1:7999/file/download/24071411085841900.txt" download="filename.txt">点击下载文件</a>code>

2.XMLHttpRequest下载文件

关键是设置responseType,以及对响应数据二进制数据处理

function downloadFileByXHR() {

let downloadUrl = document.getElementById("downloadUrl").value; // 下载的url地址

// let downloaduUrl = "http://192.168.95.59:7999/download/file/"+fileName;

let request = new XMLHttpRequest();

request.open("GET", downloadUrl, true);

// 响应被处理为 Blob 对象,可以通过 `xhr.response` 访问响应数据,适用于处理二进制数据,如文件、图像等

request.responseType = "blob";

request.onload = function () {

if (request.status === 200) {

let contentType = request.getResponseHeader("Content-Type");

//验证响应响应数据,若异常则响应 Content-Type 为 json 认定为下载失败

if (contentType && contentType.startsWith('application/json')) {

const reader = new FileReader();

reader.onload = function () {

const text = reader.result; // 下载出错时后端返回的错误信息

console.log("text:", text);

};

reader.readAsText(request.response); // 尝试将blob数据读取为文本数据

return;

}

let disposition = request.getResponseHeader("Content-Disposition");

// Content-Disposition: attachment; filename=24070701440188300.png

const data = new Blob([request.response], { type: request.getResponseHeader("Content-Type") });

const url = window.URL.createObjectURL(data);

const link = document.createElement("a");

link.href = url;

let fileName = getFileName(disposition);

if (fileName !== "") {

link.download = fileName;

}

document.body.appendChild(link);

link.click();

document.body.removeChild(link);

window.URL.revokeObjectURL(url); // 释放内存

link.remove();

}

};

request.onerror = function () {

console.low("error:", request.responseText);

};

request.send();

}

链接下载方法

// 设置隐藏表单下载链接,点击即可下载,这种方法不够友好,若后端错误了前端直接暴露原始错误信息

function downloadLink() {

console.log("链接下载");

let link = document.getElementById("link");

link.href = "http://127.0.0.1:7999/file/download/24071415521018500.txt";

// link.download = "test.txt"; // 可指定下载后的名称

link.click();

}

3.后端文件下载处理

Controller层接收文件下载请求

@ApiOperation(value = "下载文件")

@RequestMapping(value = "/download/{fileName}", method = RequestMethod.GET)

ResponseEntity<byte[]> getDownloadFileResponse(@PathVariable("fileName") String fileName);

Service层读取文件

// 给前端响应一个字节数组,使用ResponseEntity封装以便设置HttpHeaders

public ResponseEntity<byte[]> getDownloadFileResponse(String fileName) {

byte[] imageBytes = this.getLocalFile(fileName); // 获取文件的字节数组

String contentType = getFileMediaType(fileName).toString();

try {

fileName = URLEncoder.encode(fileName, "UTF-8"); // 中文字符串编码处理避免前端收到乱码

} catch (UnsupportedEncodingException e) {

throw new RuntimeException(e);

}

HttpHeaders headers = new HttpHeaders();

// headers.add("Custom-Action", "download");

headers.add(HttpHeaders.CONTENT_TYPE, contentType); // 设置Content-Type

headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName); // 设置附件,前端点击超链接下载时该名称将作为下载的文件名称

headers.add("Access-Control-Expose-Headers", "Content-Type,Content-Disposition,Custom-Action");code>

return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);

}

// 读取磁盘指定文件为字节数组

public byte[] getLocalFile(String fileName) {

File file = new File(localFileProperties.getPath() + "/" + fileName); // 服务器文件位置

FileInputStream inputStream = null;

try {

inputStream = new FileInputStream(file);

byte[] bytes = new byte[inputStream.available()];

inputStream.read(bytes, 0, inputStream.available());

return bytes;

} catch (IOException e) {

e.printStackTrace();

log.error("获取文件失败:",e);

throw new RuntimeException("找不到指定的文件");

}

}

// 根据文件名后缀确定图片的 MIME 类型

public MediaType getFileMediaType(String imageName) {

String fileExtension = imageName.substring(imageName.lastIndexOf(".") + 1).toLowerCase();

switch (fileExtension) {

case "jpeg":

case "jpg":

return MediaType.IMAGE_JPEG;

case "png":

return MediaType.IMAGE_PNG;

case "gif":

return MediaType.IMAGE_GIF;

case "bmp":

return MediaType.parseMediaType("image/bmp");

default:

return MediaType.APPLICATION_OCTET_STREAM; // 默认为二进制流

}

}

4.后端外链请求方法

Controller层接收一个下载外链的请求

@ApiOperation(value = "第三方外链下载")

@RequestMapping(value = "/outlink/download", method = RequestMethod.GET)

ResponseEntity<byte[]> getDownloadOutlinkResponse(@RequestParam("url") String url);

Service层读取第三方服务器的文件

这里为啥前端不直接访问第三方文件服务器,因为在一些业务场景中,前端可能没有权限访问直接访问、直接访问不安全或者在对第三方外链的访问情况做分析统计时需要

public ResponseEntity<byte[]> downloadOutLink(String fileUrl) {

log.info("downloadOutLink fileUrl:{}", fileUrl);

RestTemplate restTemplate = new RestTemplate();

ResponseEntity<byte[]> responseEntity = restTemplate.exchange(fileUrl, HttpMethod.GET, null, byte[].class);

byte[] bytes = responseEntity.getBody();

log.info("return entity...");

HttpHeaders oldHeaders = responseEntity.getHeaders();

oldHeaders.entrySet().forEach(entry -> {

log.info("headName:{}, headValue:{}", entry.getKey(), entry.getValue());

});

String contentDisposition = oldHeaders.getFirst(HttpHeaders.CONTENT_DISPOSITION);

String contentType = oldHeaders.getFirst(HttpHeaders.CONTENT_TYPE);

HttpHeaders responseHeaders = new HttpHeaders();

// 新创建一个 responseHeaders 用于设置返回前端的请求头,此处没有直接使用oldHeaders,因为这样可能会暴露出现某些不被允许的请求头以至于出错

if (contentDisposition != null && !Objects.equals("", contentDisposition)) {

responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition);

} else {

// 获取一个文件扩展名

String fileSuffix = "";

if(fileUrl.contains(".")){

String suffix = fileUrl.substring(fileUrl.lastIndexOf(".")+1).toLowerCase();

if(suffix.length()>0 && suffix.length()<5){

fileSuffix = suffix;

}

}

if(Objects.equals(fileSuffix,"")){

fileSuffix = "download";

}

String fileName = System.currentTimeMillis()+"."+fileSuffix;

responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s",fileName));

}

responseHeaders.add(HttpHeaders.CONTENT_TYPE, contentType);

return ResponseEntity.ok()

.headers(responseHeaders)

.body(bytes);

}

Fetch API下载文件

function downloadFileByFetch() {

// const url = 'http://127.0.0.1:7999/file/upload'; // 文件的URL

let url = document.getElementById("downloadUrl").value;

fetch(url)

.then(async (response) => {

console.log("response:", response);

if (!response.ok) {

throw new Error('Network response was not ok ' + response.statusText);

}

const contentType = response.headers.get('Content-Type');

// 后端抛出异常时,返回json数据

if(contentType && contentType.startsWith("application/json")){

const jsonResponse = await response.json();

if (jsonResponse.code === 1) {

// 后端返回了统一错误响应

console.error('Request failed with message:', jsonResponse.msg);

showInfo(JSON.stringify(jsonResponse));

return;

}

}

console.log("contentType:",contentType);

const disposition = response.headers.get('Content-Disposition');

console.log("disposition:", disposition);

let fileName = "unknown.download";

if (disposition !== null) {

const fileNameMatch = disposition.match(/filename="?([^"]+)"?/);code>

if (fileNameMatch.length === 2) {

fileName = fileNameMatch[1];

}

fileName = fileName.replace(/\+/g, ' ');

fileName = decodeURI(fileName);

}

response.blob().then(blob => {

const url = window.URL.createObjectURL(blob);

const a = document.createElement('a');

a.style.display = 'none';

a.href = url;

a.download = fileName; // 设置下载文件名

document.body.appendChild(a);

a.click();

window.URL.revokeObjectURL(url); // 释放URL对象

});

})

.catch(error => {

console.error('error:', error);

});

}

Axios下载文件

const downloadFileByAxios = () => {

// 使用 Axios 发起 GET 请求

// let url = "http://192.168.95.59:7999/download/file/xxx";

let url = document.getElementById("downloadUrl").value;

let httpHeaders = { };

// httpHeaders = { "Custom-Action": "RQ-download" };

axios.get(url, { responseType: 'blob', headers: httpHeaders })

.then(response => {

// 请求成功处理

console.log("收到下载数据:", response);

// let res = response.data;

handleAxiosDownloadResponse(response.data, response.headers);

}).catch(error => {

// 请求失败处理

console.error('Error fetching posts:', error);

});

}

// 处理axios下载的响应文件

const handleAxiosDownloadResponse = async (data, headers) => {

const contentType = headers['content-type'];

// 后端返回的不是文件而是json对象,判断为异常

if (contentType && contentType.startsWith("application/json")) {

// data.text()返回一个Promise对象,因此要使用await,此时方法使用使用async关键字标识为异步方法

let text = await data.text();

console.log("text:", text);

const jsonObj = JSON.parse(text);

if (jsonObj.code === 1) {

console.log("请求异常:", text);

}

showInfo(text);

return;

}

const blob = new Blob([data], { type: headers['content-type'] });

// 创建一个指向 Blob 对象的 URL

const url = window.URL.createObjectURL(blob);

// 创建一个 <a> 元素,并设置其 href 属性指向 Blob URL

const a = document.createElement('a');

a.href = url;

// 从响应头或其他方式获取文件名

const contentDisposition = headers['content-disposition'];

console.log("content-disposition:", contentDisposition)

let fileName = '';

if (contentDisposition) {

const fileNameMatch = contentDisposition.match(/filename="?([^"]+)"?/);code>

if (fileNameMatch.length === 2) {

fileName = fileNameMatch[1];

}

fileName = fileName.replace(/\+/g, ' '); // 将符号+替换为空格

fileName = decodeURI(fileName);

// console.log("fileName:",fileName);

}

a.download = fileName; // 设置下载文件名

// 将 <a> 元素添加到 DOM 并触发点击事件

document.body.appendChild(a);

a.click();

// 移除 <a> 元素并释放 Blob URL

document.body.removeChild(a);

window.URL.revokeObjectURL(url);

}

Axios读取文件内容

const readFileContentByAxios = () => {

// 使用 Axios 发起 GET 请求

// let url = "http://192.168.95.59:7999/download/file/xxx";

let url = document.getElementById("downloadUrl").value;

let httpHeaders = { };

// responseType选项取值与XMLHttpRequest的responseType一样,指定为arraybuffer,表示响应被处理为 ArrayBuffer 对象,适用于处理原始二进制数据

axios.get(url, { responseType: 'arraybuffer', headers: httpHeaders })

.then(async (response) => {

// 请求成功处理

console.log("收到数据:", response);

// let res = response.data;

const text = new TextDecoder('utf-8').decode(new Uint8Array(response.data));

console.log(text);

})

.catch(error => {

// 请求失败处理

console.error('Error fetching posts:', error);

});

}

参考资料

1.XMLHttpRequest(XHR)对象

2.Fetch API接口指南

3.Axios API中文文档

4.Spring Framework文档



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。