为了账号安全,请及时绑定邮箱和手机立即绑定

构建multipart/form-data实现文件上传

标签:
Java

构建multipart/form-data实现文件上传

通常文件上传都是通过form表单中的file控件,并将form中的content-type设置为multipart/form-data。现在我们通过java来构建这部分请求内容实现文件上传功能。

一、关于multipart/form-data

文件上传本质上是一个POST请求。只不过请求头以及请求内容遵循一定的规则(协议)

  • 请求头(Request Headers)中需要设置 Content-Type 为 multipart/form-data; boundary=${boundary}。其中${boundary}分割线,需要在代码中替换,且尽量复杂,不易重复

  • 请求正文(Request Body)需要使用在 Header中设置的 ${boundary}来分割当前正文中的FormItem,内容格式如下

    复制代码

    --${boundary}
    Content-Disposition: form-data; name="id"
     
    testCodeUpload
    --${boundary}
    Content-Disposition: form-data; name="file";filename="xx.txt"
    Content-Type: application/octet-stream
     
    {{这里写入文件流}}
    --${boundary}--

    复制代码

    正文开始以前缀+${boundary}开始,以 前缀 +${boundary}+前缀结束。中间每个FormItem 以 前缀+${boundary}开始,以一个空白的换行结束。

二、代码实现

实例代码采用HttpURLConnection实现一个简单POST请求

  • 建立http请求,设置基本参数

复制代码

URL postUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) postUrl.openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("Charset", "UTF-8");

复制代码

  • 添加文件上传必须的请求信息,获取http请输出流

String boundary = "----" + UUID.randomUUID().toString();
conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + boundary);
OutputStream out = conn.getOutputStream();
StringBuilder sb = new StringBuilder();
  • 一组FormItem

复制代码

sb.append(boundaryPrefix);
sb.append(boundary);
sb.append(newLine);
sb.append("Content-Disposition: form-data; name=\"id\"");
sb.append(newLine);
sb.append(newLine);
sb.append("testCodeUpload");
sb.append(newLine);

复制代码

  • 文件写人

复制代码

sb.append(boundaryPrefix);
sb.append(boundary);
sb.append(newLine);
sb.append("Content-Disposition: form-data; name=\"file\"; filename=\""
+ fileName + "\"");
sb.append("Content-Type: application/octet-stream");
sb.append(newLine);
sb.append(newLine);
out.write(sb.toString().getBytes());
File file = new File(file1);
FileInputStream in = new FileInputStream(file);byte[] bufferOut = new byte[1024];int bytes = 0;while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
out.write(newLine.getBytes());
in.close();

复制代码

 

  • 结束标志 前缀+boundary +前缀

byte[] end_data = (newLine + boundaryPrefix + boundary + boundaryPrefix + newLine)
.getBytes();
out.write(end_data);
out.flush();
out.close();

三、文件接收

  • 文件接收端通过迭代每个FileItem获取不同的数据

复制代码

FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");try {
  items = upload.parseRequest(request);
} catch (FileUploadException ex) {
  ex.printStackTrace();
  out.println(ex.getMessage());  return;
}
Iterator<FileItem> itr = items.iterator();
String id = "", fileName = "";int chunks = 1, chunk = 0;
FileItem tempFileItem = null;while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();if (item.getFieldName().equals("id")) {
  id = item.getString();
} else if (item.getFieldName().equals("name")) {
  fileName = new String(item.getString().getBytes("ISO-8859-1"), "UTF-8");
} else if (item.getFieldName().equals("file")) {
  tempFileItem = item;
}

复制代码

四、总结

 

通过代码实现一遍文件上传,了解其运行机制,解开了以前在写文件上传代码中item.getFieldName().equals("name")等相关判断的疑惑。所以,对于已有的基础代码,还是多看,多写,多实践。

附完整代码

复制代码

 1 @Test 2     public void buildUploadStream() throws IOException { 3         String url ="uploadurl"; 4         file1 = "D:\\test.xls"; 5         fileName = "test.xls"; 6          7         String newLine = "\r\n"; 8         String boundaryPrefix = "--"; 9         String boundary = "----" + UUID.randomUUID().toString();10 11         URL postUrl = new URL(url);12         HttpURLConnection conn = (HttpURLConnection) postUrl.openConnection();13 14         conn.setRequestMethod("POST");15         conn.setDoInput(true);16         conn.setDoOutput(true);17         conn.setUseCaches(false);18 19         conn.setRequestProperty("connection", "Keep-Alive");20         conn.setRequestProperty("Charset", "UTF-8");21         conn.setRequestProperty("Content-Type",22                 "multipart/form-data; boundary=" + boundary);23 24         OutputStream out = conn.getOutputStream();25 26         27         StringBuilder sb = new StringBuilder();28 29         sb.append(boundaryPrefix);30         sb.append(boundary);31         sb.append(newLine);32 33         sb.append("Content-Disposition: form-data; name=\"id\"");34         sb.append(newLine);35         sb.append(newLine);36         sb.append("testCodeUpload");37         sb.append(newLine);38 39         sb.append(boundaryPrefix);40         sb.append(boundary);41         sb.append(newLine);42 43         sb.append("Content-Disposition: form-data; name=\"name\"");44         sb.append(newLine);45         sb.append(newLine);46         sb.append(fileName);47         sb.append(newLine);48 49         sb.append(boundaryPrefix);50         sb.append(boundary);51         sb.append(newLine);52 53         sb.append("Content-Disposition: form-data; name=\"file\"; filename=\""54                 + fileName + "\"");55         sb.append("Content-Type: application/octet-stream");56         sb.append(newLine);57         sb.append(newLine);58 59         out.write(sb.toString().getBytes());60         61         File file = new File(file1);62         FileInputStream in = new FileInputStream(file);63         byte[] bufferOut = new byte[1024];64         int bytes = 0;65         while ((bytes = in.read(bufferOut)) != -1) {66             out.write(bufferOut, 0, bytes);67         }68         out.write(newLine.getBytes());69         in.close();70         byte[] end_data = (newLine + boundaryPrefix + boundary + boundaryPrefix + newLine)71                 .getBytes();72         out.write(end_data);73         out.flush();74         out.close();75 76         BufferedReader reader = new BufferedReader(new InputStreamReader(77                 conn.getInputStream()));78         String line = null;79         while ((line = reader.readLine()) != null) {80             System.out.println(line);81         }82     }

复制代码

all code

 

原文出处:https://www.cnblogs.com/yfrs/p/uploadbyjavacode.html  

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消