前面通过PHP调用CURL实现了断点上传,但在用JAVA做文件上传时遇到了些问题
问题1:上传片段文件不成功
JAVA有个HttpComponents包http://hc.apache.org/downloads.cgi 进行上传开始使用的是MultipartEntityBuilder方式,上传整个文件没有任何问题,但是在分片时会发现计算的片的长度和实际post的Content-Length比是偏小的,仔细对比发现是由于上面这种方式会在正文里使用boundary包装一些上传内容所属的字段和类型等信息,后来同事就用AbstractHttpEntity 这个底层类来封装要上传的内容,上传就可以了。
问题2: 使用httppost设置header中文乱码的问题
还没有来的急高兴,发现了另一个小问题,发送的header里指定的filename如果为中文则会乱码,但是我通过curl发送的中文却不会,而且仔细对比过都是utf-8编码。通过curl设置代理到charles上抓包发现,抓包里面是乱的,但是php接收到的是正常的。所以应该是支持的,只是中间有做什么处理。继续尝试java调用方法,在检查MultipartEntityBuilder方式上传时设置的字符集和上传模式为兼容浏览器模式后能显示正常中文,所以进一步肯定了MultipartEntityBuilder也是做了某些处理了,追踪源码发现了org/apache/http/Consts.class 这个类里发现有
public static final Charset UTF_8 = Charset.forName("UTF-8"); public static final Charset ASCII = Charset.forName("US-ASCII"); public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
于是分别尝试转码成这三种编码的文件名,最终发现在使用ISO-8859-1时服务端可以正常显示。
代码片段:
HttpPost httppost = new HttpPost("http://dev.upload.com/upload.php"); // 代理抓包 HttpHost proxy = new HttpHost("127.0.0.1", 8888, "http"); // 文件内容 File mp4File = new File("/tmp/aaa.mp4"); int length = (int)mp4File.length(); System.out.println("文件长度:" + length); // 读取片段 FileInputStream in = new FileInputStream(mp4File); DataInputStream dis= new DataInputStream(in); byte[] itemBuf = new byte[length]; dis.read(itemBuf, 0, length); ByteArrayEntity fileEntity = new ByteArrayEntity(itemBuf, 0 , 2); System.out.println("post长度" + String.valueOf(fileEntity.getContentLength())); // 中文文件名要转成ISO编码不然会乱码 String name = "hello中国人.mp4"; String iso = new String(name.getBytes("utf-8"), "ISO-8859-1"); httppost.setHeader("Content-Disposition", "attachment; name=\"file1\"; filename=\""+iso+"\""); httppost.setHeader("Cookie", "User=loginUser;"); httppost.setHeader("X-Content-Range", "bytes 0-" + (fileEntity.getContentLength() - 1) + "/" + length); httppost.setHeader("Session-ID", "111"); RequestConfig config = RequestConfig.custom().setProxy(proxy).build(); httppost.setEntity(fileEntity); httppost.setConfig(config); CloseableHttpResponse response = httpclient.execute(httppost);
完整代码放在:https://github.com/keminar/nginx-upload-module/tree/master/example/java