整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Java 实现 FastDFS 实现文件的上传、下载

Java 实现 FastDFS 实现文件的上传、下载、删除

一个成功人士的背后,必定曾经做出过勇敢而又孤独的决定。

放弃不难,但坚持很酷~

最近在项目上完成了附件上传和下载功能,是用的 fastdfs 来实现的。好记性不如烂笔头,今天把关键代码记录下来,方便以后复用。

一、Base64 转 图片url

1)在 pom.xml 中添加依赖:

<!--fastdfs-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-fastdfs</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

2)在 application.yml 中添加 fastdfs 相关配置:

fdfsIp: http://fastdfs:8880/

fastdfs:
connecttimeout-in-seconds: 5
network-timeout-in-seconds: 10
charset: UTF-8
# token 防盗链功能
http-anti-steal-token: false
# 密钥
http-secret-key: FastDFS1234567890
# TrackerServer port
http-tracker-http-port: 8888
# 测试环境
tracker-server-list:
- fastdfs:22122

示例代码:

上述方法就是将图片的 base64 码进行转换并上传到了 fastdfs 上。以下是可复制粘贴的源码:

import org.springframework.fasfdfs.exception.FdfsException;
import org.springframework.fasfdfs.server.FastDFSClient;

@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

@Value("${fdfsIp}")
private String fdfsIp;

@Autowired
private FastDFSClient fastDFSClient;

/**
* 保存用户信息
*
* @param userDto DTO 对象
* @return success/fail
*/
@Override
@Transactional(rollbackFor=Exception.class)
public Boolean saveUser(UserDTO userDto) {

// 图片base64转换为图片url
String imgBase64=userDto.getAvatar;
if (!StrUtil.isBlank(imgBase64)) {
String imageUri=;
try {
imageUri=fdfsIp + fastDFSClient.uploadFileWithBase64(imgBase64, ".jpg");
} catch (FdfsException e) {
log.error("图片上传fastdfs异常", e);
}
if (StrUtil.isBlank(imageUri)) {
log.info("图片转换失败!");
return false;
}
userDto.setAvatar(imageUri);
}

// ...
}
}

二、文件(word、pdf)上传到 fastdfs

关于像 word、pdf 这样的文件上传到 fastdfs,我是通过 fastdfs-client-java 这个 jar 包来实现:

1)在 pom.xml 文件中添加依赖:

<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27-SNAPSHOT</version>
</dependency>

2)添加 fastdfs_client.conf 文件

#jar中使用时需要将此文件名修改为fastdfs_client.conf 。
#也可以在jar被调用方resource下加入fastdfs_client.conf 内容如下
connect_timeout=60
network_timeout=120
charset=UTF-8
http.tracker_http_port=8888
http.anti_steal_token=no
http.secret_key=FastDFS1234567890

tracker_server=fastdfs:22122

3)相关代码实现

fastdfs 文件属性相关:

@Data
public class FastDFSFile implements Serializable {

private static final long serialVersionUID=2637755431406080379L;

/**
* 文件二进制
*/
private byte content;

/**
* 文件名称
*/
private String name;

/**
* 文件长度
*/
private Long size;

public FastDFSFile(byte[] content, String name, Long size){
this.content=content;
this.name=name;
this.size=size;
}
}

fastdfs 工具类相关(包含初始化 fatdfs 连接,上传、下载、删除文件):

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.io.IOException;
import java.io.Serializable;

/**
* @author liuyzh
* @description fastdfs上传文件,参考链接:https://blog.wuwii.com/fsds-java.html
* @date 2020-03-03
*/
@Slf4j
public class FastDFSUtils implements Serializable {

private static final long serialVersionUID=-4462272673174266738L;
private static TrackerClient trackerClient;
private static TrackerServer trackerServer;
private static StorageClient1 storageClient1;

static {
try {
//clientGloble读配置文件
ClientGlobal.init("fastdfs_client.conf");
//trackerclient
trackerClient=new TrackerClient;
trackerServer=trackerClient.getConnection;
//storageclient
storageClient1=new StorageClient1(trackerServer, );
} catch (Exception e) {
e.printStackTrace;
}
}

/**
* fastDFS文件上传
*
* @param file 上传的文件 FastDFSFile
* @return String 返回文件的绝对路径
*/
public static String uploadFile(FastDFSFile file) {
String path=;
try {
//文件扩展名
String ext=FilenameUtils.getExtension(file.getName);
//mata list是表文件的描述
NameValuePair mata_list=new NameValuePair[3];
mata_list[0]=new NameValuePair("fileName", file.getName);
mata_list[1]=new NameValuePair("fileExt", ext);
mata_list[2]=new NameValuePair("fileSize", String.valueOf(file.getSize));
path=storageClient1.upload_file1(file.getContent, ext, mata_list);
} catch (Exception e) {
e.printStackTrace;
}
return path;
}

/**
* fastDFS文件下载
*
* @param groupName 组名
* @param remoteFileName 文件名
* @param specFileName 真实文件名
* @return ResponseEntity<byte >
*/
public static ResponseEntity<byte> downloadFile(String groupName, String remoteFileName, String specFileName) {
byte content=;
HttpHeaders headers=new HttpHeaders;
try {
content=storageClient1.download_file(groupName, remoteFileName);
headers.setContentDispositionFormData("attachment", new String(specFileName.getBytes("UTF-8"), "iso-8859-1"));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
} catch (Exception e) {
e.printStackTrace;
}
return new ResponseEntity<byte>(content, headers, HttpStatus.CREATED);
}

/**
* 删除fastdfs文件
* @param storagePath 文件的全部路径 如:group1/M00/00/00/wKgRsVjtwpSAXGwkAAAweEAzRjw471.jpg
* @return -1失败,0成功
* @throws IOException
* @throws Exception
*/
public static Boolean deleteFile(String storagePath) {
int result=-1;
try {
result=storageClient1.delete_file1(storagePath);
} catch (IOException | MyException e) {
log.error("fastdfs删除文件异常:", e);
}
if (result==-1) {
return false;
} else {
return true;
}
}

/**
* 根据fastDFS返回的path得到文件的组名
* @param path fastDFS返回的path
* @return
*/
public static String getGroupFormFilePath(String path){
return path.split("/")[0];
}

/**
* 根据fastDFS返回的path得到文件名
* @param path fastDFS返回的path
* @return
*/
public static String getFileNameFormFilePath(String path) {
return path.substring(path.indexOf("/")+1);
}
}

上传代码示例:

@Override
@SneakyThrows
public R uploadFile(MultipartFile file) {

JSONObject jsonObject=new JSONObject;
try {
Long fileSize=file.getSize;
// 检查文件大小,不能超过5M
if (fileSize >=5 * 1024 * 1024) {
return R.failed("附件大小不允许超过5M");
}
String attachmentName=file.getOriginalFilename;
FastDFSFile fastDFSFile=new FastDFSFile(file.getBytes, file.getOriginalFilename, file.getSize);
String attachmentPath=FastDFSUtils.uploadFile(fastDFSFile);

jsonObject.put("attachmentPath", attachmentPath);
jsonObject.put("attachmentName", attachmentName);
jsonObject.put("attachmentSize", OtherUtil.getFileSizeUnit(fileSize));
return R.ok(jsonObject);
} catch (IOException e) {
log.info("上传附件异常:", e);
}
return R.failed("附件上传异常");
}

下载代码示例(两种):

  • 方式一:

/**
* 案件所属附件下载
* 接口 demo:http://192.168.166.189:7700/case/download?path=group1/M00/03/CF/wKinzF5d-EOAWPuEAAGjUNtaNqM02.docx
*
* @param path fastdfs返回的路径
* @return
*/
@RequestMapping(value="/download")
public ResponseEntity<byte> download(String path) {

// 根据附件url获取附件名称
AttachmentInfo attachmentInfo=attachmentInfoService.getAttachmentInfoByUrl(path);
// 下载后的文件名称
String specFileName=attachmentInfo.getFileName;

String filename=FastDFSUtils.getFileNameFormFilePath(path);
String group=FastDFSUtils.getGroupFormFilePath(path);
return FastDFSUtils.downloadFile(group, filename, specFileName);
}

这样就可以实现浏览器下载了。不过还可以用 nginx 的方式来完成文件的下载:

  • 方式二:

在 nginx 的 fastdfs 相关 server 配置里面添加:

if ($arg_attname ~* .(doc|docx|txt|pdf|zip|rar|xls|xlsx|png|jpeg|jpg)$) {
add_header Content-Disposition "attachment;filename=$arg_attname";
}

如下图所示:

重启 nginx 后,这样就可以通过访问 url 来进行文件下载了。

比如:http://fastdfs:8880/group1/M00/03/CF/wKinzF5d-EOAWPuEAAGjUNtaNqM02.docx?attname=测试.docx

删除代码示例:

/**
* @param storagePath 文件的全部路径 如:group1/M00/00/00/wKgRsVjtwpSAXGwkAAAweEAzRjw471.jpg
* @return -1失败,0成功
* @throws IOException
* @throws Exception
*/
public static Boolean deleteFile(String storagePath) {
int result=-1;
try {
result=storageClient1.delete_file1(storagePath);
} catch (IOException | MyException e) {
log.error("fastdfs删除文件异常:", e);
}
if (result==-1) {
return false;
} else {
return true;
}
}

三、小结

关于 fastdfs 的文件上传、下载、删除的示例代码上面都已经介绍清楚了,如果有小伙伴遇到了 fastdfs jar 包的依赖问题,也不要慌,我已经踩过坑了,出坑记录:实操:Could not autowire No beans of 'FastDFS Client' type found 的解决方法 ,可以看这篇。

点关注,不迷路

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才

白嫖不好,创作不易。也感谢各位的支持和认可,给予我最大的创作动力吧,我们下篇文章见!

如果本篇博客有任何错误,请批评指教,不胜感激 !

? Ambari 2.7.3.0 安装部署 hadoop 3.1.0.0 集群视频完整版

? 【实战】使用 Kettle 工具将 mysql 数据增量导入到 MongoDB 中

? 都快2020年了,ambari自定义服务集成,你还没掌握吗?文末有福利

? HBase原理(一):架构理解

? HBase二次开发之搭建HBase调试环境,如何远程debug HBase源代码

? Kafka消费者 之 指定位移消费

? Kylin配置Spark并构建Cube(修订版)

? 看完您如果还不明白 Kerberos 原理,算我输!

欢迎大家留言讨论

朕已阅

Flask中,文件上传通常涉及创建一个表单,用户可以通过这个表单上传文件。然后,后端代码会处理接收到的文件。以下是实现文件上传功能的步骤:

创建HTML表单 - 使用标签创建一个表单,设置enctype="multipart/form-data"属性以支持文件上传。

File Upload


创建Flask路由 - 定义一个处理文件上传的路由。

from flask import Flask, request, redirect, url_for, send_from_directory

app=Flask(__name__)

@app.route('/upload', methods=['GET', 'POST'])

def upload_file():

if request.method=='POST':

file=request.files['file']

if file and '.jpg' in file.filename:

# 保存上传的文件

filename='uploads/' + file.filename

file.save(filename)

# 重定向到文件上传后的页面

return redirect(url_for('success', filename=filename))

return '''

'''

@app.route('/success/')

def success(filename):

# 返回上传成功的页面,显示文件名和下载链接

return f'File uploaded successfully: Download {filename}'

@app.route('/download_file/')

def download_file(filename):

return send_from_directory(app.root_path + '/uploads', filename)

if __name__=="__main__":

app.run()


处理上传的文件 - 在Flask视图函数中,通过request.files字典访问上传的文件。

保存上传的文件 - 将上传的文件保存到服务器的指定目录中。

重定向或返回上传结果 - 一旦文件被保存,可以重定向用户到一个新页面,显示上传成功的信息,或者直接在原页面显示上传结果。

提供下载链接 - 为了让用户能够下载上传的文件,可以创建一个路由来提供文件的下载服务。在示例中,使用了send_from_directory函数来实现。

确保服务器上的目标目录对于Web服务是可写的,并且处理上传的代码要考虑安全性,比如检查文件类型、大小,防止上传恶意文件。此外,对于生产环境,应该使用更高级的文件上传处理方案,比如文件存储在外部服务上,以及设置适当的权限和安全措施。

于网页的上传组件比较常用的webuploader ,jQuery File Upload等,切图网在做前端项目切图的时候,不乏有一些后台或者前台需要用到上传组件的,虽然做前端开发不需要实现上传到服务器的功能,但是前台的功能还是需要做出来的,特别简单的可以jquery手写 基本能够用了,而复杂的时候就需要上一些插件,而选择插件的时候也比较讲究,插件尽可能要灵活 参数够多 或者一些扩展方法多, 可以满足不同的复杂情况,而jQuery File Upload则是相比之下比较不错的一款。

jQuery File Upload 是一个Jquery文件上传组件,支持多文件上传、取消、删除,上传前缩略图预览、列表显示图片大小,支持上传进度条显示;支持各种动态语言开发的服务器端。

官网链接:https://github.com/blueimp/jQuery-File-Upload/wiki

特点:拖放支持;上传进度条;图像预览;可定制和可扩展的;兼容任何服务器端应用平台(PHP, Python, Ruby on Rails, Java, Node.js, Go etc.)。

演示地址 https://blueimp.github.io/jQuery-File-Upload/

使用方法:

1. 需要加载的js文件:

jquey-1.8.3.min.js

jquery-ui-widget.js

jquery.iframe-transport.js

jquery.fileupload.js

2. html代码:

  1. <input id=“fileupload” type=“file” name=“files[]” data-url=“server/php/” multiple>

3. js代码:

  1. $(function () {
  2. $(‘#fileupload’).fileupload({
  3. dataType: ‘json’,
  4. done: function (e, data) {
  5. $.each(data.result.files, function (index, file) {
  6. $(‘<p/>’).text(file.name).appendTo(document.body);
  7. });
  8. }
  9. });
  10. });

3.1 显示上传进度条:

  1.  $(‘#fileupload’).fileupload({
  2.   progressall: function (e, data) {
  3.   var progress=parseInt(data.loaded / data.total * 100, 10);
  4.   $(‘#progress .bar’).css(
  5.   ‘width’,
  6.   progress + ‘%’
  7.   );
  8.   }
  9.   });

3.2 需要一个<div>容器用来显示进:

  1.  <div id=“progress”>
  2.   <div class=“bar” style=“width: 0%;“></div>
  3.   </div>

4. API

4.1 Initialization:

在上传按钮上调用fileupload()方法;

示例:

$('#fileupload').fileupload();

4.2 Options :

1: url:请求发送的目标url

Type: string

Example: ‘/path/to/upload/handler.json’

2.Type: 文件上传HTTP请求方式,可以选择“POST”,“PUT”或者”PATCH”,

默认”POST”

Type: string

Example: ‘PUT’

3. dataType:希望从服务器返回的数据类型,默认”json”

Type: string

Example: ‘json’

4. autoUpload:默认情况下,只要用户点击了开始按钮被添加至组件的文件会立即上传。将autoUpload值设为true可以自动上传。

Type: boolean

Default: true

5. acceptFileTypes:允许上传的的文件类型

Example: /(\.|\/)(gif|jpe?g|png|xlsx)$/i

6. maxFileSize: 最大上传文件大小

Example: 999000 (999KB) //单位:B

7. minFileSize:最小上传文件大小

Example: 100000 (100KB) //单位:B

8.previewMaxWidth : 图片预览区域最大宽度

Example: 100 //单位:px

4.3 Callback Options:

使用方法一:函数属性

实例:

  1. $(‘#fileupload’).fileupload({
  2.   drop: function (e, data) {
  3.   $.each(data.files, function (index, file) {
  4.   alert(‘Dropped file: ‘ + file.name);
  5.   });
  6.   },
  7.   change: function (e, data) {
  8.   $.each(data.files, function (index, file) {
  9.   alert(‘Selected file: ‘ + file.name);
  10.   });
  11.   }
  12.   });

使用方法二:绑定事件监听函数

实例:

  1. $(‘#fileupload’)
  2.     .bind(‘fileuploaddrop’, function (e, data) {/* … */})
  3.     .bind(‘fileuploadchange’, function (e, data) {/* … */});

每个事件名称都添加前缀:”fileupload”;

注意推荐使用第二种方法。

常用的回调函数:

1. add: 当文件被添加到上传组件时被触发

  1. $(‘#fileupload’).bind(‘fileuploadadd’, function (e, data) {/* … */});

或者$(‘#fileupload’).on(‘fileuploadadd’, function (e, data) {/* … */});

2. processalways: 当一个单独的文件处理队列结束(完成或失败时)触发

3. progressall: 全局上传处理事件的回调函数

Example:

  1. $(‘#fileupload’).on(‘fileuploadprogressall’, function (e, data) { //进度条显示
  2. var progress=parseInt(data.loaded / data.total * 100, 10);
  3. $(‘#progress .progress-bar’).css(
  4. ‘width’,
  5. progress + ‘%’
  6. );
  7. });

4. fail : 上传请求失败时触发的回调函数,如果服务器返回一个带有error属性的json响应这个函数将不会被触发。

5. done : 上传请求成功时触发的回调函数,如果服务器返回一个带有error属性的json响应这个函数也会被触发。

6. always : 上传请求结束时(成功,错误或者中止)都会被触发。