1. Preface
Recently, we are maintaining an old Web project, which uses DWR 2.0 (a remote communication framework that can call Java methods in js). Now we need to use this framework to upload files to and download files from the server. However, DWR 2.0 used in this project only supports calling Java methods with basic data types, String, List, Map and other common types as parameters and return values by default. We cannot use FileTransfer, InputStream, MultipartFile and other objects.
Since you can pass strings, you can use the method of file and string mutual conversion to interact before and after. The process is as follows:
When uploading a file, file - > arraybuffer - > hexadecimal string - > byte [] - > file
When downloading a file, file - > byte [] - > hexadecimal string - > uint8array - > blob - > file
2. Upload files
HTML code:
<input type="file" multiple="multiple" onchange="readFilesAndUpload(event)" />
JS Code:
// Convert ArrayBuffer to hexadecimal string 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) // file name var fileContextArr = new Array(len) // Document content for (var i = 0; i < len; ++i) { var reader = new FileReader() reader.index = i reader.filename = files[i].name reader.readAsArrayBuffer(files[i]) // Read file to ArrayBuffer reader.onload = function (e) { filenameArr[this.index] = this.filename fileContextArr[this.index] = bufToHex(this.result) // FileReader reads files asynchronously. It needs to use external variables to determine whether all files have been read if (++processed === len) { // Upload filenameArr and fileContext to the server } } } }
Java code:
private static final String UPLOAD_DIR = "D://Files/"; public void uploadFiles(List<String> filenameArr, List<String> fileContextArr) throws IOException { byte[] bytes; FileOutputStream fos; for (int i = 0; i < filenameArr.size(); ++i) { String file = fileContextArr.get(i); // Convert hexadecimal string to byte [] bytes = new byte[file.length() / 2]; 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); } // Save to local disk fos = new FileOutputStream(UPLOAD_DIR + filenameArr.get(i), true); fos.write(bytes); fos.close(); } }
3. Download files
Java code:
public String downloadFile(String filename) throws IOException { File file = new File(UPLOAD_DIR + filename); if (!file.exists()) { return null; } // Read file to byte [] byte[] buffer = new byte[(int) file.length()]; InputStream is = new FileInputStream(file); is.read(buffer); is.close(); // Convert byte [] to hexadecimal string 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 Code:
// Conversion of hexadecimal string to integer array 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() { // Call the server method to get the hexadecimal string res var uint8Array = new Uint8Array(hexToBytes(res)) var blob = new Blob([uint8Array], {type: "application/octet-stream"}) // Compatible with IE, Firefox and Google if (window.navigator && window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(blob, filename) } 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) } }