如何实现ftp的文件上传于下载

    第一步准备一个ftp服务器;
    最基本的ftp文件夹下应该有public的文件和private的文件,一般公开的文件是直接从浏览器中访问的,而私有的文件是必须通过ftp的方式和下载,基于此逻辑,就需要给到http网址;
    第二步准备导入maven:

    1. <dependency>
    2. <groupId>commons-io</groupId>
    3. <artifactId>commons-io</artifactId>
    4. <version>2.4</version>
    5. </dependency>

    第三步导入当前代码

    1. package com.yuxin.yijia.utils.ftp;
    2. import org.apache.commons.io.FileUtils;
    3. import org.apache.commons.net.ftp.FTP;
    4. import org.apache.commons.net.ftp.FTPClient;
    5. import org.apache.commons.net.ftp.FTPReply;
    6. import org.springframework.core.io.ClassPathResource;
    7. import org.springframework.core.io.Resource;
    8. import org.springframework.core.io.support.PropertiesLoaderUtils;
    9. import java.io.File;
    10. import java.io.FileInputStream;
    11. import java.io.IOException;
    12. import java.io.InputStream;
    13. import java.util.Properties;
    14. public class FileFtpUtil {
    15. private String ftpIp;
    16. private int port;
    17. private String username;
    18. private String password;
    19. private String baseUrl;
    20. private Resource resource = new ClassPathResource("yijia.properties");
    21. private FileFtpUtil() {
    22. //读取
    23. try {
    24. Properties props = PropertiesLoaderUtils.loadProperties(resource);
    25. ftpIp = props.getProperty("ftpIp");
    26. port = Integer.parseInt(props.getProperty("port", "21"));
    27. username = props.getProperty("username");
    28. password = props.getProperty("password");
    29. baseUrl = props.getProperty("baseUrl", "/image");
    30. } catch (Exception e) {
    31. System.err.println("ftp配置初始化失败,原因:" + e);
    32. e.printStackTrace();
    33. }
    34. }
    35. public static FileFtpUtil getInstance() {
    36. return Inner.instance;
    37. }
    38. private static class Inner {
    39. private static final FileFtpUtil instance = new FileFtpUtil();
    40. }
    41. /**
    42. * @param file 需要上传的文件
    43. * @param filename 上传的----文件名.后缀 例:c.png 不带路径
    44. * @param path 文件路径,如果没有此路径则会创建文件夹
    45. * @throws IOException
    46. */
    47. public boolean picreate(File file, String filename, String path) throws IOException {
    48. //创建一个FtpClient对象
    49. FTPClient ftpClient = new FTPClient();
    50. //创建ftp连接,默认是:21端口
    51. ftpClient.connect(ftpIp, port);
    52. //登录ftp服务器,使用用户名 和密码
    53. ftpClient.login(username, password);
    54. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    55. int reply;
    56. // 获取ftp登录应答代码
    57. reply = ftpClient.getReplyCode();
    58. // 验证是否登陆成功
    59. if (!FTPReply.isPositiveCompletion(reply)) {
    60. ftpClient.disconnect();
    61. System.err.println("FTP server refused connection.");
    62. }
    63. //上传文件
    64. //读取本地文件
    65. FileInputStream inputStream = new FileInputStream(file);
    66. //设置上传的路径
    67. if (!path.startsWith("/"))
    68. path = "/" + path;
    69. if (!baseUrl.startsWith("/"))
    70. baseUrl = "/" + baseUrl;
    71. path = baseUrl + path;
    72. // String fullpath = "ftp://" + ftpIp + ":" + port + path;
    73. String d;
    74. try {
    75. //目录编码,解决中文路径问题
    76. d = new String(path.toString().getBytes("GBK"), "iso-8859-1");
    77. //尝试切入目录
    78. if (!ftpClient.changeWorkingDirectory(d)) {
    79. String[] arr = path.split("/");
    80. StringBuffer sbfDir = new StringBuffer();
    81. //循环生成子目录
    82. for (String s : arr) {
    83. if (s == null || s.trim().equals(""))
    84. continue;
    85. sbfDir.append("/");
    86. sbfDir.append(s);
    87. //目录编码,解决中文路径问题
    88. d = new String(sbfDir.toString().getBytes("GBK"), "iso-8859-1");
    89. //尝试切入目录
    90. if (ftpClient.changeWorkingDirectory(d))
    91. continue;
    92. if (!ftpClient.makeDirectory(d)) {
    93. System.out.println("[失败]ftp创建目录:" + sbfDir.toString());
    94. ftpClient.logout();
    95. return false;
    96. }
    97. System.out.println("[成功]创建ftp目录:" + sbfDir.toString());
    98. }
    99. //将目录切换至指定路径
    100. if (!ftpClient.changeWorkingDirectory(d)) {//切换到指定目录
    101. ftpClient.logout();
    102. return false;
    103. }
    104. }
    105. } catch (Exception e) {
    106. e.printStackTrace();
    107. ftpClient.logout();
    108. return false;
    109. }
    110. //修改上传文件的格式
    111. //第一个参数:服务器端文档名
    112. //第二个参数:上传文档的inputStream
    113. boolean res = ftpClient.storeFile(filename, inputStream);
    114. System.out.println("上传文件" + filename + ":" + res);
    115. //关闭连接
    116. ftpClient.logout();
    117. return true;
    118. }
    119. /**
    120. * @param httpUrl 文件的网络地址,请确定是上传到ftp上的文件
    121. * @return
    122. */
    123. public boolean del4Http(String httpUrl) throws IOException {
    124. //创建一个FtpClient对象
    125. FTPClient ftpClient = new FTPClient();
    126. //创建ftp连接,默认是:21端口
    127. ftpClient.connect(ftpIp, port);
    128. //登录ftp服务器,使用用户名 和密码
    129. ftpClient.login(username, password);
    130. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    131. int reply;
    132. // 获取ftp登录应答代码
    133. reply = ftpClient.getReplyCode();
    134. // 验证是否登陆成功
    135. if (!FTPReply.isPositiveCompletion(reply)) {
    136. ftpClient.disconnect();
    137. System.err.println("FTP server refused connection.");
    138. }
    139. //设置上传的路径
    140. if (!httpUrl.startsWith("http"))
    141. return false;
    142. String filePath = httpUrl.substring(httpUrl.indexOf(baseUrl));
    143. if (!baseUrl.startsWith("/"))
    144. baseUrl = "/" + baseUrl;
    145. int index = filePath.lastIndexOf("/");
    146. if (index == -1) {
    147. System.err.println("文件路径异常:" + filePath);
    148. ftpClient.logout();
    149. return false;
    150. }
    151. String path = filePath.substring(0, index);
    152. System.out.println(path);
    153. if (!ftpClient.changeWorkingDirectory(path)) {//切换到指定目录
    154. System.err.println("文件路径不存在:" + filePath);
    155. ftpClient.logout();
    156. return false;
    157. }
    158. System.out.println(filePath.substring(index + 1));
    159. if (!ftpClient.deleteFile(filePath.substring(index + 1))) {
    160. System.err.println("文件删除失败:" + filePath);
    161. ftpClient.logout();
    162. return false;
    163. }
    164. ftpClient.logout();
    165. System.err.println("文件已删除:" + filePath);
    166. return true;
    167. }
    168. public File download4Http(String httpUrl) throws IOException {
    169. //创建一个FtpClient对象
    170. FTPClient ftpClient = new FTPClient();
    171. //创建ftp连接,默认是:21端口
    172. ftpClient.connect(ftpIp, port);
    173. //登录ftp服务器,使用用户名 和密码
    174. ftpClient.login(username, password);
    175. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    176. int reply;
    177. // 获取ftp登录应答代码
    178. reply = ftpClient.getReplyCode();
    179. // 验证是否登陆成功
    180. if (!FTPReply.isPositiveCompletion(reply)) {
    181. ftpClient.disconnect();
    182. System.err.println("FTP server refused connection.");
    183. }
    184. if (!baseUrl.startsWith("/"))
    185. baseUrl = "/" + baseUrl;
    186. //设置上传的路径
    187. // if (!httpUrl.startsWith("http"))
    188. // return null;
    189. int i = httpUrl.indexOf(baseUrl);
    190. //如果上传路径中没有baseUrl,则应该是相对路径,则追加baseUrl
    191. String filePath = null;
    192. if (i == -1) {
    193. filePath = baseUrl + httpUrl;
    194. } else {
    195. filePath = httpUrl.substring(i);
    196. }
    197. int index = filePath.lastIndexOf("/");
    198. if (index == -1) {
    199. System.err.println("文件路径异常:" + filePath);
    200. ftpClient.logout();
    201. ftpClient.disconnect();
    202. return null;
    203. }
    204. String path = filePath.substring(0, index);
    205. System.out.println(path);
    206. if (!ftpClient.changeWorkingDirectory(path)) {//切换到指定目录
    207. System.err.println("文件路径不存在:" + filePath);
    208. ftpClient.logout();
    209. ftpClient.disconnect();
    210. return null;
    211. }
    212. String name = filePath.substring(index + 1);
    213. System.out.println(name);
    214. File file = new File(filePath.substring(index + 1));
    215. if (ftpClient.retrieveFile(name, FileUtils.openOutputStream(file))) {
    216. System.out.println("文件下载成功:" + path + ",length:" + file.length());
    217. ftpClient.logout();
    218. ftpClient.disconnect();
    219. return file;
    220. } else {
    221. System.out.println("文件下载失败:" + path);
    222. ftpClient.logout();
    223. ftpClient.disconnect();
    224. return file;
    225. }
    226. // ftpClient.enterLocalPassiveMode(); // 设置被动模式,开通一个端口来传输数据
    227. }
    228. /**
    229. * 删除那种
    230. *
    231. * @param filePath
    232. * @return
    233. * @throws IOException
    234. */
    235. public boolean del(String filePath) throws IOException {
    236. //创建一个FtpClient对象
    237. FTPClient ftpClient = new FTPClient();
    238. //创建ftp连接,默认是:21端口
    239. ftpClient.connect(ftpIp, port);
    240. //登录ftp服务器,使用用户名 和密码
    241. ftpClient.login(username, password);
    242. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    243. int reply;
    244. // 获取ftp登录应答代码
    245. reply = ftpClient.getReplyCode();
    246. // 验证是否登陆成功
    247. if (!FTPReply.isPositiveCompletion(reply)) {
    248. ftpClient.disconnect();
    249. System.err.println("FTP server refused connection.");
    250. }
    251. //设置上传的路径
    252. if (!filePath.startsWith("/"))
    253. filePath = "/" + filePath;
    254. if (!baseUrl.startsWith("/"))
    255. baseUrl = "/" + baseUrl;
    256. filePath = baseUrl + filePath;
    257. int index = filePath.lastIndexOf("/");
    258. if (index == -1) {
    259. System.err.println("文件路径异常:" + filePath);
    260. ftpClient.logout();
    261. return false;
    262. }
    263. String path = filePath.substring(0, index);
    264. System.out.println(path);
    265. if (!ftpClient.changeWorkingDirectory(path)) {//切换到指定目录
    266. System.err.println("文件路径不存在:" + filePath);
    267. ftpClient.logout();
    268. return false;
    269. }
    270. System.out.println(filePath.substring(index + 1));
    271. if (!ftpClient.deleteFile(filePath.substring(index + 1))) {
    272. System.err.println("文件删除失败:" + filePath);
    273. ftpClient.logout();
    274. return false;
    275. }
    276. ftpClient.logout();
    277. System.err.println("文件已删除:" + filePath);
    278. return true;
    279. }
    280. /**
    281. * 判断某个文件(不是文件夹)存在吗
    282. *
    283. * @param filePath 文件或者文件夹路径
    284. * @return
    285. */
    286. public boolean isExit(String filePath) throws IOException {
    287. //创建一个FtpClient对象
    288. FTPClient ftpClient = new FTPClient();
    289. //创建ftp连接,默认是:21端口
    290. ftpClient.connect(ftpIp, port);
    291. //登录ftp服务器,使用用户名 和密码
    292. ftpClient.login(username, password);
    293. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    294. int reply;
    295. // 获取ftp登录应答代码
    296. reply = ftpClient.getReplyCode();
    297. // 验证是否登陆成功
    298. if (!FTPReply.isPositiveCompletion(reply)) {
    299. ftpClient.disconnect();
    300. System.err.println("连接FTP SERVER失败,SERVER IP[" + ftpIp + port + "], Ftp response:" + ftpClient.getReplyString());
    301. return false;
    302. }
    303. //设置上传的路径
    304. if (!filePath.startsWith("/"))
    305. filePath = "/" + filePath;
    306. if (!baseUrl.startsWith("/"))
    307. baseUrl = "/" + baseUrl;
    308. filePath = baseUrl + filePath;
    309. InputStream inputStream = ftpClient.retrieveFileStream(filePath);
    310. if (inputStream == null || ftpClient.getReplyCode() == 550) {
    311. System.out.println("FTP SERVER上未找到以下文件[" + filePath + "]");
    312. return false;
    313. }
    314. ftpClient.logout();
    315. return true;
    316. }
    317. public static void main(String[] args) {
    318. // try {
    319. // FileFtpUtil.picreate(new File("D:\\360MoveData\\Users\\sz\\Pictures\\Saved Pictures\\改革办平台整理2.png"), "/qinglu/888/fff.png");
    320. // } catch (IOException e) {
    321. // e.printStackTrace();
    322. // }
    323. FileFtpUtil ftp = new FileFtpUtil();
    324. // try {
    325. // ftp.del("/course/48996/20191111/0b16f709-1c5e-4b1d-a096-ad13b20c1f1b.jpg");
    326. // } catch (IOException e) {
    327. // e.printStackTrace();
    328. // }
    329. try {
    330. File file = ftp.download4Http("http://192.168.0.115/image/temp/48996/20191114/e3792e70-44e6-484b-a0f7-0690527f5185.jpg");
    331. System.out.println(file.length());
    332. } catch (IOException e) {
    333. e.printStackTrace();
    334. }
    335. // try {
    336. // System.out.println(ftp.del4Http(path));
    337. // } catch (IOException e) {
    338. // e.printStackTrace();
    339. // }
    340. //
    341. // String sub = path.substring(path.indexOf("/image"));
    342. // System.out.println(sub);
    343. }
    344. }

    第四步:在Controller中调用此静态方法

    1. package com.yuxin.yijia.controller;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import com.yuxin.wx.util.ToolStr;
    5. import com.yuxin.wx.utils.FileUtil;
    6. import com.yuxin.wx.utils.PropertiesUtil;
    7. import com.yuxin.wx.utils.WebUtils;
    8. import com.yuxin.yijia.utils.ftp.FileFtpUtil;
    9. import com.yuxin.yijia.utils.rest.ResultJson;
    10. import org.apache.commons.lang.ArrayUtils;
    11. import org.springframework.beans.factory.annotation.Autowired;
    12. import org.springframework.stereotype.Controller;
    13. import org.springframework.web.bind.annotation.RequestMapping;
    14. import org.springframework.web.bind.annotation.RequestMethod;
    15. import org.springframework.web.bind.annotation.ResponseBody;
    16. import org.springframework.web.multipart.MultipartFile;
    17. import org.springframework.web.multipart.MultipartRequest;
    18. import java.io.File;
    19. import java.io.IOException;
    20. import java.util.Iterator;
    21. @Controller
    22. public class FileController {
    23. public static final String base = "/fileupload";
    24. public static final String save = base + "/save";
    25. public static final String up = base + "/up";
    26. public static final String del = base + "/del";
    27. public static final String get = base + "/get";
    28. @Autowired
    29. private PropertiesUtil propertiesUtil;
    30. /**
    31. * 实现删除旧的图片上传新的图片,而且还要保证其原子性,不考虑网络连接不稳定的情况(因为解决不了)
    32. *
    33. * @param multiPartRquest 上传的文件内容
    34. * @param module 该文件对应的模块(根据其找到文件的前缀)
    35. * @param oldPath 需要删除的文件,如果有路径的话携带路径
    36. * @return
    37. */
    38. @ResponseBody
    39. @RequestMapping(value = up, method = RequestMethod.POST)
    40. public JSONObject upPic(MultipartRequest multiPartRquest, String module, String oldPath) throws IOException {
    41. boolean flag = false;
    42. //先看看是不是真的有原来的文件
    43. try {
    44. if (ToolStr.isEmpty(oldPath)) {
    45. return ResultJson.of(4000, "请传入原图片地址");
    46. }
    47. String basepath = propertiesUtil.getImageServicePath();
    48. int basepathIndex = oldPath.indexOf(basepath);
    49. oldPath = oldPath.substring(basepathIndex + basepath.length());
    50. if (FileFtpUtil.getInstance().isExit(oldPath)) {
    51. flag = true;
    52. }
    53. } catch (IOException e) {
    54. e.printStackTrace();
    55. }
    56. //监控一下是不是只有一个文件
    57. if (multiPartRquest.getFileMap().size() > 1) {
    58. return ResultJson.of(4000, "只能上传1个文件");
    59. }
    60. // System.out.println(multiPartRquest.getMultiFileMap().size());
    61. // System.out.println(multiPartRquest.getFileMap().size());
    62. if (flag) {
    63. flag = false;
    64. //如果是有则开始进行文件上传
    65. JSONObject res = null;
    66. try {
    67. res = uploadFile(multiPartRquest, getPrefix(module));
    68. if (res.getInteger("code") == 200) {
    69. flag = true;
    70. }
    71. } catch (IOException e) {
    72. e.printStackTrace();
    73. }
    74. //文件上传成功后则执行删除 oldPath
    75. if (flag) {
    76. flag = false;
    77. try {
    78. if (FileFtpUtil.getInstance().del(oldPath)) {
    79. flag = true;
    80. return res;
    81. } else {
    82. System.err.println("FTP:删除文件" + oldPath + "异常");
    83. return res;
    84. }
    85. } catch (IOException e) {
    86. e.printStackTrace();
    87. }
    88. if (!flag) {
    89. //如果删除失败则需要再删除新上传的图片
    90. JSONObject data = res.getJSONObject("data");
    91. if (data != null) {
    92. String url = data.getString("url");
    93. if (url != null) {
    94. boolean ok = FileFtpUtil.getInstance().del(url);//删除新上传的文件
    95. if (ok) {
    96. return ResultJson.of(4002, "文件上传成功后删除失败,已成功回滚");
    97. } else {
    98. return ResultJson.of(4002, "文件上传成功后删除失败,回滚失败,新文件已上传");
    99. }
    100. }
    101. }
    102. return ResultJson.of(4002, "文件上传成功后删除失败,回滚失败,新文件已上传");
    103. } else {
    104. return res;
    105. }
    106. } else {
    107. return ResultJson.of(4001, "文件上传异常");
    108. }
    109. // return ResultJson.of(4001, "文件上传异常");
    110. } else {
    111. return ResultJson.of(4000, "oldPath不存在");
    112. }
    113. }
    114. /**
    115. * 获取前缀
    116. *
    117. * @param module
    118. */
    119. private String getPrefix(String module) {
    120. if (ToolStr.isEmpty(module)) {
    121. module = FileUtil.Module.TEMP;
    122. }
    123. return FileUtil.getPath(module, WebUtils.getCurrentCompanyId().toString());
    124. }
    125. /**
    126. * FTP上传图片,保存图片
    127. *
    128. * @param multiPartRquest 上传的文件
    129. * @param module (分类)模块名称参考下面的类,如果传空默认是temp类型
    130. * @return
    131. * @see FileUtil.Module
    132. */
    133. @ResponseBody
    134. @RequestMapping(value = save, method = RequestMethod.POST)
    135. public JSONObject queryPic(MultipartRequest multiPartRquest, String module) {
    136. if (ToolStr.isEmpty(module)) {
    137. module = FileUtil.Module.TEMP;
    138. }
    139. String path = FileUtil.getPath(module, WebUtils.getCurrentCompanyId().toString());
    140. // String contentType = mfile.getContentType();
    141. // String checkExcelFileType = checkExcelFileType(contentType);
    142. try {
    143. return uploadFile(multiPartRquest, path);
    144. } catch (IOException e) {
    145. e.printStackTrace();
    146. return ResultJson.of(4000, "文件上传异常");
    147. }
    148. }
    149. public static final String[] File_Type = {"default", "xlsx", "xls", "doc", "docx", "ppt", "pptx", "pdf", "txt", "zip", "rar", "png", "jpg", "jpeg",
    150. "3gp", "avi", "flv", "mp4", "mkv", "mov", "ogg", "wmv", "gif", "del", "", "", "", "", ""};
    151. /**
    152. * 文件类型是不是对应的文件
    153. *
    154. * @param contentType
    155. * @return
    156. */
    157. // 判断文件类型
    158. public static boolean checkFileType(String contentType) {
    159. int a = contentType.indexOf(".");
    160. if (a != -1) {
    161. return ArrayUtils.contains(File_Type, contentType);
    162. } else {
    163. String str = contentType.substring(a, contentType.length());
    164. return ArrayUtils.contains(File_Type, str);
    165. }
    166. }
    167. // 判断文件类型
    168. public static String checkExcelFileType(String contentType) {
    169. switch (contentType) {
    170. case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
    171. return ".xlsx";
    172. case "application/vnd.ms-excel":
    173. return ".xls";
    174. case "application/msword":
    175. return ".doc";
    176. case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
    177. return ".docx";
    178. case "application/pdf":
    179. return ".pdf";
    180. case "text/plain":
    181. return ".txt";
    182. case "application/zip":
    183. return ".zip";
    184. case "application/octet-stream":
    185. return ".rar";
    186. case "application/x-png":
    187. return ".png";
    188. case "image/png":
    189. return ".png";
    190. case "application/x-jpg":
    191. return ".jpg";
    192. case "image/jpeg":
    193. return ".jpeg";
    194. case "video/3gpp":
    195. return ".3gp";
    196. case "video/x-msvideo":
    197. return ".avi";
    198. case "video/x-flv":
    199. return ".flv";
    200. case "video/mp4":
    201. return ".mp4";
    202. case "video/x-matroska":
    203. return ".mkv";
    204. case "video/quicktime":
    205. return ".mov";
    206. case "video/x-theora+ogg":
    207. return ".ogg";
    208. case "video/x-ms-wmv":
    209. return ".wmv";
    210. case "image/gif":
    211. return ".gif";
    212. }
    213. return "";
    214. }
    215. /**
    216. * 实现文件上传到ftp
    217. *
    218. * @param multiPartRquest 携带文件的对象
    219. * @param prefix 文件的路径(前缀)
    220. * @return
    221. * @throws IOException
    222. */
    223. private JSONObject uploadFile(MultipartRequest multiPartRquest, String prefix) throws IOException {
    224. JSONObject data = new JSONObject();
    225. JSONArray arr = new JSONArray();
    226. Iterator iter = multiPartRquest.getFileNames();
    227. while (iter.hasNext()) {
    228. MultipartFile multipartFile = multiPartRquest.getFile(iter.next().toString());
    229. // MultipartFile multipartFile = multiPartRquest.getFile("imgData");
    230. //被注释掉的是老的使用方式
    231. // String realPath = null;
    232. // realPath = FileUtil.upload(multipartFile, "temp", WebUtils.getCurrentCompanyId()+"");
    233. //通过ftp方式上传图片或者文件
    234. String fileName = FileUtil.generateFileName(multipartFile.getOriginalFilename());
    235. if (checkFileType(fileName)) {
    236. return ResultJson.of(4001, "文件类型异常");
    237. }
    238. File file = new File(fileName);
    239. // file = File.createTempFile("/qinglu/a/", ".jpg");
    240. multipartFile.transferTo(file);
    241. FileFtpUtil.getInstance().picreate(file, fileName, prefix);
    242. // FileFtpUtil.picreate(multipartFile.getInputStream(), path + fileName);
    243. file.deleteOnExit();//程序退出时删除临时文件
    244. //上传文件
    245. // req.getSession().setAttribute("imgData", multipartFile);
    246. String url = "/" + prefix + fileName;
    247. arr.add(url);
    248. }
    249. if (arr.size() == 0) {
    250. return ResultJson.of(4000, "没有任何文件上传");
    251. }
    252. //判断是不是一个文件
    253. if (arr.size() == 1) {
    254. data.put("url", arr.get(0));
    255. } else {
    256. //如果是多个文件放到list中
    257. data.put("list", arr);
    258. }
    259. return ResultJson.of(200, data);
    260. }
    261. }

    如此即可实现上传和下载