文件上传原理

文件上传 I/O流

最最最简易版
流程图
请添加图片描述
代码实现

客户端

public class Client {
    public static void main(String[] args) throws IOException {
        //创建一个Socket连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);

        //获取输出流
        OutputStream outputStream = socket.getOutputStream();

        //读取文件
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要上传的文件地址:");
        String Filename = scanner.next();

        FileInputStream fileInputStream = new FileInputStream(new File(Filename));

        //写入文件到输出流中
        byte[] buffer=new byte[1024];
        int len;
        while ((len = fileInputStream.read(buffer))!=-1){
            outputStream.write(buffer,0,len);
        }

        //关闭资源
        fileInputStream.close();
        scanner.close();
        outputStream.close();
        socket.close();
    }
}

服务端

public class Server {
  public static void main(String[] args) throws IOException {
    //创建服务
    ServerSocket serverSocket = new ServerSocket(9000);
    //监听客户端的连接
    Socket socket = serverSocket.accept();
    //获取输入流
    InputStream is = socket.getInputStream();


    //文件输出
    FileOutputStream fileOutputStream = new FileOutputStream(new File("server.jpg"));
    byte[] buffer =new byte[1024];
    int len;
    while ((len=is.read(buffer))!=-1){
      fileOutputStream.write(buffer,0,len);
    }

    //关闭资源
    fileOutputStream.close();
    is.close();
    socket.close();
    serverSocket.close();

  }
}

当然这中间应该加上许多的判断,为了解原理,一切从简

文件上传 web版

大部分内容转载于https://www.cnblogs.com/niujifei/p/15160813.html

前端:

  1. 使用form表单 method=post 请求
  2. form标签的encType属性值必须为multipart/form-data值
  3. 在form标签中使用input type=file添加上传的文件
  4. 服务端接收处理上传到的数据

前端表单

<form action="" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="userName" >
    头像:<input type="file" name="photo">
    <input type="submit" value="上传">
</form>

前端上传文件http协议
在这里插入图片描述
上面分别是请求函、请求体(上面的请求体具体样式如下

------WebKitFormBoundaryddHJFAhQaKAYu4fI--

------WebKitFormBoundaryjGOWvhVJTetIHzBJ
Content-Disposition: form-data; name="userName"


------WebKitFormBoundaryjGOWvhVJTetIHzBJ
Content-Disposition: form-data; name="photo"; filename="2023&#31038;&#20250;&#23454;&#36341;.docx"
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document

PK
     �N�@            	   docProps/PK   �N�@�cթi  {     docProps/app.xml���N?0D�H�C�{b;M�E[?���R="��6�m?ѿǡ��+��Ye�������WF/S��4A-M��~?>7��<M|?�ѸL��k~~kg,��?'1B�eڅ`��A?<�u��?D������[#?ԁ�^?�[l3{
��<?l�豎�|'z�@~?1��?��܎o��?5'|[��2�j�~I'+XY?+)Bl�oכ�黝W��?䬜���=��?7uV\,꬜Um�bU�Ѫ�J:���W@�I�ݠ|w*ƃLe<�d?PK   �N�@[�\�D  Z     docProps/core.xml}�QK?0��?C�{��ձ��{�@?2?-$w[�IK���M��N�s�w��M?<?*?c�Zg�F�E-K}��K??(��kɫZC?:�h��ޤ�a?6�d??+?��-M��?5c+�����C{q_ŝ??n�x??1!3��q??=0l&"�RL���T@
#?��?��)8qV��M��j����x!M
֎K?;p?��?%�Ң���{���g�Rl\ZD1?#6?�p��[�_��bg;�۞F��%���	۷)x�²�BB��KH0)`??#�iA?:������x?n��?�m'f��??}��a|1Vg?��d?8A�a��??	?6w������ ��UH��?(?(_�uT?�hM���߄��Z�_fPK
     �N�@               word/PK   �N�@�B�DQ
  �g     word/styles.xml�]�v����Z}W�E?8?$3Y?9k&?ͬ��i��\? ?:?��y�^?=?��iߣ[B`��ڰ{?��m�ϒ���O�q?=?,2������I C?<N�����{����,?	��/<?��??|\���K�s ��,&��(ҳ?(?<f��Ly_.d?>f���e�V�^ �b."Q��N|#'?*K?�^,�L�rQ�K��b!n�TWd��W^�`�Ќ��G`�L�H?
,�zc??)d�,7 ������'P��V��ە.��_xH?"�,y�?��?8�?a�U��c_?3!3(ĉ?�9x#�o<?@�P��?<�|x�Jh?Yqj��Bm�Jl����A?$L9�NY)Q?,9S��w!zkyihq?�?�q�w?!N�C���x?�C+D��Iȟ;n ��4 ?=9 nO???y ��? ?=? n/??	
��Ey(X��P?��`	
C?��?%(
KP
�� ,A9?!?+�l$��?G)�D?+?3<K \��T��g�~?7����2?��.?.�h�L��[z�W?!?'�B<?2���{1��G0L�X%C?�F?	u	e|?3?(��s4�?%	��U<��?+*e�V��IjM#tOJ
���d�M�z��F??S
j�v=��ϸ����_?_���ռ���)�V���5?,	?S�W"�n*�LP;E�ݩ�&�H$ڿi�t?��ǰ/cL��-�vDp������%?�S|�|�d?5?���E&;z?�\���"�af�w����?#XB�E�{��$�?&v�Y̴��~��?����?fo��?
�j>V�~.(~*Kh?
kh?&?$?,?&����%?%U�ϳk�{?ի?
��N�w�@��ɻS?`d��?w��xI�c???1?J`�}??�_�c��[A;R��G?#e��?#?


可以看到中间一大串乱码其实是上传的文件转为一个二进制的流。
而服务端的任务就是将这个二进制流解析成一个文件,存入服务器中

服务端

Commons-fileupload.jar 常用 API

使用的是commons-fileupload.jar包,使用该jar包需要依赖如下io的jar包
在这里插入图片描述

1、常用API与类
FileItemFactory      表单项工厂接口
ServletFileUpload    文件上传类,用于解析上传的数据
FileItem             表单项类,表示每一个表单项
boolean ServletFileUpload.isMultipartContent(HttpServletRequest request)   判断当前上传的数据格式是否是多段的格式,只有是多段数据,才能使用该方式
public List<FileItem> parseRequest(HttpServletRequest request)             解析上传的数据,返回包含 表单项的 List 集合
boolean FileItem.isFormField()       判断当前这个表单项,是否是普通的表单项,还是上传的文件类型,true 表示普通类型的表单项;false 表示上传的文件类型
String FileItem.getFieldName()       获取表单项的 name 属性值
String FileItem.getString()           获取当前表单项的值;
 
String FileItem.getName()          获取上传的文件名
void FileItem.write( file )        将上传的文件写到 参数 file 所指向存取的硬盘位置

服务端Servlet实现


import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;

import java.util.List;


public class uploadFileServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//        ServletInputStream inputStream = req.getInputStream();
//
//        byte[] buffer=new byte[10240];
//        int read = inputStream.read(buffer);
//
//        System.out.println(new String(buffer,0,read));



        //如果传入的文件数据不是多段的,只有是多段数据,才能使用该方式
        boolean isMultipart= ServletFileUpload.isMultipartContent(req);
        if(isMultipart){
			//设置上传的文件的文件夹
            String realpath=req.getSession().getServletContext().getRealPath("/files");
            System.out.println(realpath);
			//dir是即将传入的文件的对象,在realpath路径下
            File dir=new File(realpath);
            if(!dir.exists()) dir.mkdirs();
            //创建FileItemFactory工厂实现类
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //创建用于解析上传数据的工具类ServletFileUpload
            ServletFileUpload upload=new ServletFileUpload(factory);
            upload.setHeaderEncoding("UTF-8");

            try {
                //解析上传的数据,得到每一个表单项items
                List<FileItem> items=upload.parseRequest(req);
                System.out.println(items.size());
                for (FileItem item:items){
                    if (item.isFormField()){//普通表单项
                        String name1=item.getFieldName();//得到请求参数名称
                        String value=item.getString("UTF-8");
                        System.out.println(name1+"="+value);
                    }else {//上传的文件
                    //将这个上传的文件以时间戳的命名方式存入
                        String urlString=System.currentTimeMillis()+item.getName().substring(item.getName().lastIndexOf("."));
						//将解析出来的文件内容放到dir这个对象中,并且以urlString命名
                        item.write(new File(dir,urlString));



                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }


        }

    }
}

流程图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值