如何在不转为Base64字符串的情况下将JavaScript Blob上传至JSF?
不转Base64,通过JSF组件上传Blob音频文件
这里提供两种实用方案,分别对应PrimeFaces的<p:remoteCommand>和原生JSF的<h:commandScript>,全程无需将Blob转换为Base64字符串:
方案一:使用PrimeFaces <p:remoteCommand>
1. 后端ManagedBean实现
创建支持文件上传的Bean,用于接收并处理音频文件:
import org.primefaces.model.file.UploadedFile; import javax.faces.view.ViewScoped; import javax.inject.Named; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; @Named @ViewScoped public class AudioUploadBean { private UploadedFile audioFile; public void uploadAudio() { if (audioFile == null) return; try { // 替换为你的实际保存路径 Files.write(Paths.get("/opt/audio/" + audioFile.getFileName()), audioFile.getContent()); } catch (IOException e) { e.printStackTrace(); // 可在此添加Faces消息提示错误 // FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("上传失败:" + e.getMessage())); } } // Getter & Setter public UploadedFile getAudioFile() { return audioFile; } public void setAudioFile(UploadedFile audioFile) { this.audioFile = audioFile; } }
2. 前端页面配置
在xhtml页面中定义remoteCommand,并编写JS上传逻辑:
<!-- 绑定Bean的uploadAudio方法 --> <p:remoteCommand name="uploadAudioCmd" action="#{audioUploadBean.uploadAudio}" process="@this" ajax="true" /> <script> // 假设recordedBlob是你录制好的音频Blob对象 function uploadAudioBlob() { const formData = new FormData(); // 参数名必须和Bean中的audioFile属性完全一致 formData.append('audioFile', recordedBlob, 'my-recorded-audio.wav'); // 调用remoteCommand,传入FormData并禁用自动处理数据和内容类型 uploadAudioCmd({ form: formData, contentType: false, processData: false }); } </script>
方案二:使用原生JSF <h:commandScript>
1. 后端Bean
可直接复用方案一中的AudioUploadBean,无需额外修改。
2. 前端页面配置
通过commandScript获取请求URL,用XMLHttpRequest发送FormData:
<!-- 绑定Bean的uploadAudio方法 --> <h:commandScript name="uploadAudioScript" action="#{audioUploadBean.uploadAudio}" render="@none" /> <script> function uploadAudioBlob(recordedBlob) { const formData = new FormData(); formData.append('audioFile', recordedBlob, 'my-recorded-audio.wav'); const xhr = new XMLHttpRequest(); // 获取commandScript生成的请求地址 const requestUrl = uploadAudioScript.action; xhr.open('POST', requestUrl, true); // 不要手动设置Content-Type,浏览器会自动添加正确的multipart边界 xhr.send(formData); // 处理上传结果 xhr.onload = function() { if (xhr.status === 200) { console.log('音频上传成功'); } else { console.error('音频上传失败,状态码:' + xhr.status); } }; } </script>
关键注意事项
- 确保项目已配置文件上传支持:PrimeFaces需在
web.xml中添加org.primefaces.webapp.filter.FileUploadFilter;原生JSF需依赖javax.servlet.annotation.MultipartConfig或容器的文件上传配置 - FormData中append的参数名必须和ManagedBean的属性名严格匹配,否则无法完成参数绑定
- 禁止手动设置
Content-Type: multipart/form-data,浏览器会自动处理边界参数,手动设置会导致上传失败 - Bean需使用
@ViewScoped或更宽的作用域,避免请求时Bean被重新实例化导致属性丢失
内容的提问来源于stack exchange,提问作者Bashar Issa
相关产品推荐
相关产品推荐

