内容简介:最近在维护一个比较老的 Web 项目,其中用到了 DWR 2.0 (一种可以在 js 里调用 Java 方法的远程通信框架)。现在要利用这个框架实现上传文件到服务端和从服务端下载文件,然而这个项目用的 DWR 2.0,默认只支持调用以基本数据类型,以及String、 List、Map 等常用类型作为参数和返回值的 Java 方法,无法使用 FileTransfer、InputStream、MultipartFile 这些对象。既然可以传递字符串,那就采用文件与字符串互转的方式进行前后交互。流程如下:上传文件
1. 前言
最近在维护一个比较老的 Web 项目,其中用到了 DWR 2.0 (一种可以在 js 里调用 Java 方法的远程通信框架)。现在要利用这个框架实现上传文件到服务端和从服务端下载文件,然而这个项目用的 DWR 2.0,默认只支持调用以基本数据类型,以及String、 List、Map 等常用类型作为参数和返回值的 Java 方法,无法使用 FileTransfer、InputStream、MultipartFile 这些对象。
既然可以传递字符串,那就采用文件与字符串互转的方式进行前后交互。流程如下:
上传文件时,文件 -> ArrayBuffer -> 16 进制字符串 -> byte[] -> 文件
下载文件时,文件 -> byte[] -> 16 进制字符串 -> Uint8Array -> blob -> 文件
2. 上传文件
HTML 代码:
<input type="file" multiple="multiple" onchange="readFilesAndUpload(event)" />
JS 代码:
// 将 ArrayBuffer 转为 16 进制字符串
function bufToHex(buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), function (x) {
return ('00' + x.toString(16)).slice(-2)
}).join('')
}
function readFilesAndUpload(event) {
var processed = 0
var files = event.target.files
var len = files.length
var filenameArr = new Array(len) // 文件名
var fileContextArr = new Array(len) // 文件内容
for (var i = 0; i < len; ++i) {
var reader = new FileReader()
reader.index = i
reader.filename = files[i].name
reader.readAsArrayBuffer(files[i]) // 将文件读到 ArrayBuffer
reader.onload = function (e) {
filenameArr[this.index] = this.filename
fileContextArr[this.index] = bufToHex(this.result)
// FileReader 以异步的方式读取文件,需要借助外部变量判断是否读完全部文件
if (++processed === len) {
// 将 filenameArr 和 fileContext 上传到服务端
}
}
}
}
Java 代码:
private static final String UPLOAD_DIR = "D://Files/";
public void uploadFiles(List<String> filenameArr, List<String> fileContextArr) throws IOException {
FileOutputStream fos;
for (int i = 0; i < filenameArr.size(); ++i) {
String file = fileContextArr.get(i);
bytes = new byte[file.length() / 2];
// 将 16 进制字符串转换成 byte[]
for (int j = 0; j < file.length() / 2; ++j) {
String subStr = file.substring(j * 2, j * 2 + 2);
bytes[j] = (byte) Integer.parseInt(subStr, 16);
}
// 保存到本地磁盘
fos = new FileOutputStream(UPLOAD_DIR + filenameArr.get(i), true);
fos.write(bytes);
fos.close();
}
}
3. 下载文件
Java 代码:
public String downloadFile(String filename) throws IOException {
File file = new File(UPLOAD_DIR + filename);
if (!file.exists()) {
return null;
}
// 将文件读到 byte[]
byte[] buffer = new byte[(int) file.length()];
InputStream is = new FileInputStream(file);
is.read(buffer);
is.close();
// 将 byte[] 转换成 16 进制字符串
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < buffer.length; i++) {
int v = buffer[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
JS 代码:
// 16 进制字符串转换成整型数组
function hexToBytes(hexStr) {
var bytes = []
for (var c = 0; c < hexStr.length; c += 2)
bytes.push(parseInt(hexStr.substr(c, 2), 16))
return bytes
}
function downloadFile() {
// 调用服务端方法,取得 16 进制字符串 res
var uint8Array = new Uint8Array(hexToBytes(res))
var blob = new Blob([uint8Array], {type: "application/octet-stream"})
// 兼容 IE、火狐和谷歌的下载方式
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, name)
} else {
var downloadElement = document.createElement("a")
var href = window.URL.createObjectURL(blob)
downloadElement.href = href
downloadElement.download = filename
document.body.appendChild(downloadElement)
downloadElement.click()
downloadElement.remove()
window.URL.revokeObjectURL(href)
}
}
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 如何使用Perl将48个十六进制字符串转换为字节?
- HTML实体:何时使用十进制与十六进制
- python3 第十九章 - 写一个10进制转任意进制的函数
- [Java] 蓝桥杯BASIC-12 基础练习 十六进制转八进制
- 二进制手表
- 二进制状态码
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
奥美的数字营销观点
[美] 肯特·沃泰姆、[美] 伊恩·芬威克 / 台湾奥美互动营销公司 / 中信出版社 / 2009-6 / 45.00元
目前,媒体的数字化给营销人带来了重大影响。新媒体世界具有多重特性,它赋予企业大量机会,同时也带来挑战。营销人有了数量空前的方式来与消费者互动。然而,许多人面对变革的速度感到压力巨大,而且不知道该如何完全发挥这些新选择所带来的优势。 本书为读者提供了如何运用主要数字媒体渠道的方法;随附了领先的营销人如何在工作中有效运用这些渠道的最佳案例;提供了数字营销的十二个基本原则;协助数字营销人了解什么是......一起来看看 《奥美的数字营销观点》 这本书的介绍吧!