文件上传 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
前端:
- 使用form表单 method=post 请求
- form标签的encType属性值必须为multipart/form-data值
- 在form标签中使用input type=file添加上传的文件
- 服务端接收处理上传到的数据
前端表单
<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社会实践.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();
}
}
}
}