如何在JavaScript及WSO2中不依赖XMLHttpRequest发送multipart/form-data
刚好这两个问题我都有实际处理经验,给你详细拆解下:
1. 在JavaScript环境中不使用XMLHttpRequest发送multipart/form-data请求
现在几乎没人用XHR发请求了,Fetch API是更现代、更简洁的替代方案,不管是浏览器端还是Node.js环境都能轻松搞定,搭配FormData对象就能自动处理multipart/form-data的格式和头部。
举个浏览器端的实际例子:
// 先构造FormData,把表单字段和文件加进去 const formData = new FormData(); formData.append('username', 'john_doe'); // 这里假设你有个file类型的input元素,获取选中的文件 formData.append('avatar', document.getElementById('avatar-input').files[0], 'user-avatar.jpg'); // 用Fetch发送POST请求 fetch('/api/user/profile', { method: 'POST', body: formData // 直接传FormData就行,Fetch会自动设置正确的Content-Type }) .then(response => { if (!response.ok) throw new Error('请求失败'); return response.json(); }) .then(data => console.log('上传成功,返回数据:', data)) .catch(err => console.error('出问题了:', err));
如果是在Node.js环境,v18及以上已经原生支持Fetch,低版本的话可以装个node-fetch包,用法和浏览器端几乎一致。另外用axios库也很方便,它会自动识别FormData并设置头部:
const axios = require('axios'); const FormData = require('form-data'); const fs = require('fs'); const formData = new FormData(); // 读取本地文件并添加到表单 formData.append('report', fs.createReadStream('./annual-report.pdf')); formData.append('year', '2024'); axios.post('https://api.example.com/submit-report', formData, { headers: formData.getHeaders() // 让axios用FormData自动生成的头部 }) .then(res => console.log('提交成功:', res.data)) .catch(err => console.error('提交失败:', err.response?.data || err.message));
2. WSO2环境中无XMLHttpRequest时发送multipart/form-data请求
WSO2的运行环境(比如EI、APIM的JS脚本中介)用的是Java虚拟机上的JS引擎,确实不支持浏览器端的XHR或Fetch,得用WSO2兼容的方式来实现,这里给你两种常用方案:
方案一:在JS脚本中调用Apache HttpClient
WSO2内置了Apache HttpClient库,直接在脚本里调用Java类就能构造multipart请求,比如:
// 引入WSO2自带的Java类 var HttpClient = Packages.org.apache.http.impl.client.HttpClients; var HttpPost = Packages.org.apache.http.client.methods.HttpPost; var MultipartEntityBuilder = Packages.org.apache.http.entity.mime.MultipartEntityBuilder; var File = Packages.java.io.File; // 初始化客户端和POST请求 var httpClient = HttpClient.createDefault(); var postRequest = new HttpPost('https://your-target-api.com/upload'); // 构造multipart表单内容 var entityBuilder = MultipartEntityBuilder.create(); // 添加文本字段 entityBuilder.addTextBody('request-id', 'REQ-2024-001'); // 添加本地文件(注意路径是WSO2服务器上的路径) entityBuilder.addBinaryBody('attachment', new File('/opt/wso2/files/invoice.pdf')); // 把实体设置到请求里 postRequest.setEntity(entityBuilder.build()); // 发送请求并获取响应 var response = httpClient.execute(postRequest); var statusCode = response.getStatusLine().getStatusCode(); print('请求返回状态码:', statusCode); // 别忘了关闭资源 response.close(); httpClient.close();
方案二:用WSO2的中介组件实现(无脚本)
如果是在WSO2的集成序列里,直接用中介组件更规范,比如用PayloadFactory构造multipart payload,再用Send中介发送:
<sequence xmlns="http://ws.apache.org/ns/synapse"> <!-- 强制设置消息类型为multipart/form-data --> <property name="messageType" value="multipart/form-data" scope="axis2"/> <!-- 构造multipart格式的请求体 --> <payloadFactory media-type="multipart/form-data"> <format> --custom-boundary-12345 Content-Disposition: form-data; name="form-field" sample-value --custom-boundary-12345 Content-Disposition: form-data; name="upload-file"; filename="invoice.pdf" Content-Type: application/pdf $1 --custom-boundary-12345-- </format> <args> <!-- 这里从属性获取预先加载的文件内容 --> <arg evaluator="xml" expression="get-property('upload-file-content')"/> </args> </payloadFactory> <!-- 发送到目标地址 --> <send> <endpoint> <address uri="https://your-target-api.com/upload"/> </endpoint> </send> </sequence>
这种方式不需要写JS,完全用WSO2的原生中介就能搞定,适合企业级集成场景。
内容的提问来源于stack exchange,提问作者user9596637
相关产品推荐
相关产品推荐

