# 上传下载 我们对文件上传进行了分别封装了多个组件: - 单图片上传(替换图片):`src\components\pic-upload` - 多图片上传:`src\components\mul-pic-upload` - 文件上传:`src\components\file-upload` 上述这些文件上传,都是基于`el-upload`进行封装 ## 单图片上传 在商品分类这个模块的弹框中可以找到单图片上传的例子,对应vue代码位置:`src\views\modules\category-add-or-update.vue` html: ```html <pic-upload v-model="dataForm.pic"></pic-upload> ``` js: ```javascript import PicUpload from '@/components/pic-upload' export default { data () { return { dataForm: { pic: '' } }, components: { PicUpload } } ``` 这里的文件上传使用起来非常简单,只需要将最终文件上传完成后的路径进行双向绑定即可 ## 多图片上传 在商品发布这个模块的中可以找到多图片上传的例子,对应vue代码位置:`src\views\modules\category-add-or-update.vue` html: ```html <mul-pic-upload v-model="dataForm.imgs" /> ``` js: ```javascript import MulPicUpload from '@/components/mul-pic-upload' export default { data () { return { dataForm: { imgs: '' } }, components: { MulPicUpload } } ``` 这里的文件上传使用起来也非常简单,最后返回的数据,为以逗号分隔的图片路径连接的字符串 ## 服务端代码 直接的文件上传的例子与多图片上传的例子类似,这里便不一一举例了。 我们可以查看三个文件上传的源码,都有那么两句话`:action="$http.adornUrl('/admin/file/upload/element')"` `:headers="{Authorization: $cookie.get('Authorization')}"`,其中由于规定后台所有请求都需要通过 `spring security`的授权,所以需要携带通用请求头`headers`,而`action`则是对应后台服务器的路径 我们查看后台`FileController` 这里对文件上传的接口进行了统一的管理: ```java @RestController @RequestMapping("/admin/file") public class FileController { @Autowired private AttachFileService attachFileService; @PostMapping("/upload/element") public ResponseEntity<String> uploadElementFile(@RequestParam("file") MultipartFile file) throws IOException{ if(file.isEmpty()){ return ResponseEntity.noContent().build(); } String fileName = attachFileService.uploadFile(file.getBytes(),file.getOriginalFilename()); return ResponseEntity.ok(fileName); } } ``` 同时我们查看`attachFileService` 的实现类,可以知道该文件上传是通过七牛云进行实现的 ```java @Service public class AttachFileServiceImpl extends ServiceImpl<AttachFileMapper, AttachFile> implements AttachFileService { @Autowired private AttachFileMapper attachFileMapper; @Autowired private UploadManager uploadManager; @Autowired private BucketManager bucketManager; @Autowired private Qiniu qiniu; @Autowired private Auth auth; public final static String NORM_MONTH_PATTERN = "yyyy/MM/"; @Override public String uploadFile(byte[] bytes,String originalName) throws QiniuException { String extName = FileUtil.extName(originalName); String fileName =DateUtil.format(new Date(), NORM_MONTH_PATTERN)+ IdUtil.simpleUUID() + "." + extName; AttachFile attachFile = new AttachFile(); attachFile.setFilePath(fileName); attachFile.setFileSize(bytes.length); attachFile.setFileType(extName); attachFile.setUploadTime(new Date()); attachFileMapper.insert(attachFile); String upToken = auth.uploadToken(qiniu.getBucket(),fileName); Response response = uploadManager.put(bytes, fileName, upToken); Json.parseObject(response.bodyString(), DefaultPutRet.class); return fileName; } } ``` 在这里面注入了非常多的七牛云的配置,而配置文件的来源,来自 ```java @Configuration public class FileUploadConfig { @Autowired private Qiniu qiniu; /** * 华南机房 */ @Bean public com.qiniu.storage.Configuration qiniuConfig() { return new com.qiniu.storage.Configuration(Zone.zone2()); } /** * 构建一个七牛上传工具实例 */ @Bean public UploadManager uploadManager() { return new UploadManager(qiniuConfig()); } /** * 认证信息实例 * @return */ @Bean public Auth auth() { return Auth.create(qiniu.getAccessKey(), qiniu.getSecretKey()); } /** * 构建七牛空间管理实例 */ @Bean public BucketManager bucketManager() { return new BucketManager(auth(), qiniuConfig()); } } ``` ## 注册七牛云账号 现在已经9102年了,很少上传文件到本地了,一般都是上传到oss,我们这里选择[七牛云存储](https://www.qiniu.com/products/kodo) ,如果没有账号的可以注册一个,创建一个华南地区的云存储空间 ![img](https://box.kancloud.cn/c72238c384fb43c2c0b3161162880056_1909x545.png) ### 修改后台配置 找到`shop.properties` 文件 修改 ``` shop.qiniu.resourcesUrl= shop.qiniu.accessKey= shop.qiniu.secretKey= shop.qiniu.bucket= ``` ### 修改vue配置 - 在`static/config/index.js` 修改`resourcesUrl` 统一七牛云存储开发环境目录 - 在`static/config/index-prod.js` 修改`resourcesUrl` 统一七牛云存储生产环境目录